diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b0271c18b..281cb80dd 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -14,6 +14,7 @@ jobs: php: - '7.3' - '7.4' + - '8.0' symfony-versions: [false] include: - description: 'Symfony 3.4' @@ -28,6 +29,15 @@ jobs: - description: 'Symfony 5.2' php: '7.4' symfony-versions: 5.2.* + - description: 'Symfony 4.4' + php: '8.0' + symfony-versions: 4.4.* + - description: 'Symfony 5.0' + php: '8.0' + symfony-versions: 5.0.* + - description: 'Symfony 5.2' + php: '8.0' + symfony-versions: 5.2.* name: PHP ${{ matrix.php }} ${{ matrix.description }} steps: diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml index e125725a6..3e2ad9d74 100644 --- a/.github/workflows/static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -36,8 +36,6 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 - with: - php-version: '7.4' - name: Install dependencies run: composer install --no-progress --no-interaction --prefer-dist diff --git a/composer.json b/composer.json index c26f3f4e2..32e123965 100644 --- a/composer.json +++ b/composer.json @@ -20,9 +20,9 @@ ], "require": { - "php": "^7.3", + "php": "^7.3 || ^8.0", "fakerphp/faker": "^1.10", - "myclabs/deep-copy": "^1.5.2", + "myclabs/deep-copy": "^1.10", "sebastian/comparator": "^3.0 || ^4.0", "symfony/property-access": "^2.8 || ^3.4 || ^4.0 || ^5.0", "symfony/yaml": "^2.8 || ^3.4 || ^4.0 || ^5.0" diff --git a/src/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/FixtureRangeReferenceTokenParser.php b/src/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/FixtureRangeReferenceTokenParser.php index 82c7b48bc..4a6e1ee84 100644 --- a/src/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/FixtureRangeReferenceTokenParser.php +++ b/src/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/FixtureRangeReferenceTokenParser.php @@ -43,7 +43,7 @@ public function __construct() { $this->token = uniqid(__CLASS__); } - + public function canParse(Token $token): bool { return $token->getType() === TokenType::RANGE_REFERENCE_TYPE; @@ -64,7 +64,7 @@ public function parse(Token $token) $to = $range->getTo(); $step = $range->getStep(); for ($currentIndex = $from; $currentIndex <= $to; $currentIndex += $step) { - $fixtureId = str_replace($this->token, $currentIndex, $range->getName()); + $fixtureId = str_replace($this->token, (string) $currentIndex, $range->getName()); $references[] = new FixtureReferenceValue($fixtureId); } diff --git a/src/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/ParameterTokenParser.php b/src/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/ParameterTokenParser.php index 1d709916d..8a121c35a 100644 --- a/src/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/ParameterTokenParser.php +++ b/src/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/ParameterTokenParser.php @@ -28,7 +28,7 @@ final class ParameterTokenParser implements ChainableTokenParserInterface { use IsAServiceTrait; - + public function canParse(Token $token): bool { return $token->getType() === TokenType::PARAMETER_TYPE; @@ -45,7 +45,7 @@ public function parse(Token $token): ParameterValue { $value = $token->getValue(); try { - $paramKey = substr($value, 2, -2); + $paramKey = strlen($value) > 3 ? substr($value, 2, -2) : false; return new ParameterValue($paramKey); } catch (TypeError $error) { diff --git a/src/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/SimpleReferenceTokenParser.php b/src/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/SimpleReferenceTokenParser.php index 083bd86da..1219ae981 100644 --- a/src/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/SimpleReferenceTokenParser.php +++ b/src/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/SimpleReferenceTokenParser.php @@ -27,7 +27,7 @@ final class SimpleReferenceTokenParser implements ChainableTokenParserInterface { use IsAServiceTrait; - + public function canParse(Token $token): bool { return $token->getType() === TokenType::SIMPLE_REFERENCE_TYPE; @@ -41,6 +41,10 @@ public function parse(Token $token): FixtureReferenceValue $value = $token->getValue(); try { + if (!is_string($value) || '' === $value) { + throw ExpressionLanguageExceptionFactory::createForUnparsableToken($token); + } + return new FixtureReferenceValue(substr($value, 1)); } catch (InvalidArgumentException $exception) { throw ExpressionLanguageExceptionFactory::createForUnparsableToken($token, 0, $exception); diff --git a/src/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/VariableTokenParser.php b/src/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/VariableTokenParser.php index 869a8b3fe..a31428cf9 100644 --- a/src/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/VariableTokenParser.php +++ b/src/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/VariableTokenParser.php @@ -30,7 +30,7 @@ final class VariableTokenParser implements ChainableTokenParserInterface { use IsAServiceTrait; - + public function canParse(Token $token): bool { return $token->getType() === TokenType::VARIABLE_TYPE; @@ -45,7 +45,9 @@ public function canParse(Token $token): bool */ public function parse(Token $token) { - $variable = substr($token->getValue(), 1); + $variable = !is_string($token->getValue()) || $token->getValue() === '' + ? false + : substr($token->getValue(), 1); if ('current' === $variable) { return new FunctionCallValue( diff --git a/tests/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/SimpleReferenceTokenParserTest.php b/tests/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/SimpleReferenceTokenParserTest.php index ce9274042..b7366c2d8 100644 --- a/tests/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/SimpleReferenceTokenParserTest.php +++ b/tests/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/SimpleReferenceTokenParserTest.php @@ -60,7 +60,7 @@ public function testThrowsAnErrorIfAMalformedTokenIsGiven(): void $exception->getMessage() ); static::assertEquals(0, $exception->getCode()); - static::assertNotNull($exception->getPrevious()); + static::assertNull($exception->getPrevious()); } } diff --git a/tests/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/StringArrayTokenParserTest.php b/tests/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/StringArrayTokenParserTest.php index 1e8f0d449..e1c534fd2 100644 --- a/tests/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/StringArrayTokenParserTest.php +++ b/tests/FixtureBuilder/ExpressionLanguage/Parser/TokenParser/Chainable/StringArrayTokenParserTest.php @@ -71,7 +71,10 @@ public function testThrowsAnErrorIfCouldNotParseToken(): void $parser = new StringArrayTokenParser(new FakeParser()); $parser->parse($token); - static::fail('Expected exception to be thrown.'); + + if (PHP_VERSION_ID < 80000) { + static::fail('Expected exception to be thrown.'); + } } catch (ParseException $exception) { static::assertEquals( 'Could not parse the token "" (type: STRING_ARRAY_TYPE).', diff --git a/tests/FixtureBuilder/ExpressionLanguage/TokenTypeTest.php b/tests/FixtureBuilder/ExpressionLanguage/TokenTypeTest.php index e28a22392..b0738450d 100644 --- a/tests/FixtureBuilder/ExpressionLanguage/TokenTypeTest.php +++ b/tests/FixtureBuilder/ExpressionLanguage/TokenTypeTest.php @@ -26,7 +26,7 @@ class TokenTypeTest extends TestCase * @var string[] */ private $constants; - + protected function setUp(): void { $reflClass = new ReflectionClass(TokenType::class); @@ -44,10 +44,9 @@ public function testIsImmutable(): void public function testStaticValues(): void { $reflClass = new ReflectionClass(TokenType::class); - $reflProp = $reflClass->getProperty('values'); $reflProp->setAccessible(true); - $values = $reflProp->getValue(TokenType::class); + $values = $reflProp->getValue($reflClass); static::assertCount(count($this->constants), $values); foreach ($this->constants as $constant) { diff --git a/tests/Generator/Instantiator/Chainable/NoMethodCallInstantiatorTest.php b/tests/Generator/Instantiator/Chainable/NoMethodCallInstantiatorTest.php index 8b623cca6..9cd159630 100644 --- a/tests/Generator/Instantiator/Chainable/NoMethodCallInstantiatorTest.php +++ b/tests/Generator/Instantiator/Chainable/NoMethodCallInstantiatorTest.php @@ -37,7 +37,7 @@ class NoMethodCallInstantiatorTest extends TestCase * @var NoMethodCallInstantiator */ private $instantiator; - + protected function setUp(): void { $this->instantiator = new NoMethodCallInstantiator(); @@ -83,10 +83,18 @@ public function testInstantiatesWithReflectionAndNoArguments(): void (new ReflectionObject($instance))->getProperty('requiredParam'); static::fail('Expected exception to be thrown.'); } catch (ReflectionException $exception) { - static::assertEquals( - 'Property requiredParam does not exist', - $exception->getMessage() - ); + if (PHP_VERSION_ID < 80000) { + static::assertEquals( + 'Property requiredParam does not exist', + $exception->getMessage() + ); + } else { + static::assertEquals( + 'Property Nelmio\Alice\Entity\Instantiator\DummyWithRequiredParameterInConstructor::$requiredParam' + . ' does not exist', + $exception->getMessage() + ); + } } } diff --git a/tests/Generator/Resolver/Value/Chainable/EvaluatedValueResolverTest.php b/tests/Generator/Resolver/Value/Chainable/EvaluatedValueResolverTest.php index d2a86c0b1..beb1c1b89 100644 --- a/tests/Generator/Resolver/Value/Chainable/EvaluatedValueResolverTest.php +++ b/tests/Generator/Resolver/Value/Chainable/EvaluatedValueResolverTest.php @@ -77,12 +77,22 @@ public function testThrowsAnExceptionIfInvalidExpression(): void static::fail('Expected exception to be thrown.'); } catch (UnresolvableValueException $exception) { - static::assertEquals( - 'Could not evaluate the expression ""unclosed string": syntax error, unexpected end of file, expecting variable (T_VARIABLE) or ${ (T_DOLLAR_OPEN_CURLY_BRACES) or {$ (T_CURLY_OPEN)', - $exception->getMessage() - ); static::assertEquals(0, $exception->getCode()); static::assertNotNull($exception->getPrevious()); + + if (PHP_VERSION_ID < 80000) { + static::assertEquals( + 'Could not evaluate the expression ""unclosed string": syntax error, unexpected end of file,' + . ' expecting variable (T_VARIABLE) or ${ (T_DOLLAR_OPEN_CURLY_BRACES) or {$ (T_CURLY_OPEN)', + $exception->getMessage() + ); + } else { + static::assertEquals( + 'Could not evaluate the expression ""unclosed string": syntax error, unexpected end of file,' + . ' expecting variable or "${" or "{$"', + $exception->getMessage() + ); + } } } @@ -152,10 +162,17 @@ public function testVariablesInference(): void $resolver->resolve($value, $fixture, $set, $scope, new GenerationContext()); static::fail('Expected an exception to be thrown.'); } catch (UnresolvableValueException $exception) { - static::assertEquals( - 'Could not evaluate the expression "$scope": Undefined variable: scope', - $exception->getMessage() - ); + if (PHP_VERSION_ID < 80000) { + static::assertEquals( + 'Could not evaluate the expression "$scope": Undefined variable: scope', + $exception->getMessage() + ); + } else { + static::assertEquals( + 'Could not evaluate the expression "$scope": Undefined variable $scope', + $exception->getMessage() + ); + } } } @@ -190,10 +207,17 @@ public function testVariablesInferenceWithCurrent(): void $resolver->resolve($value, $fixture, $set, $scope, new GenerationContext()); static::fail('Expected an exception to be thrown.'); } catch (UnresolvableValueException $exception) { - static::assertEquals( - 'Could not evaluate the expression "$scope": Undefined variable: scope', - $exception->getMessage() - ); + if (PHP_VERSION_ID < 80000) { + static::assertEquals( + 'Could not evaluate the expression "$scope": Undefined variable: scope', + $exception->getMessage() + ); + } else { + static::assertEquals( + 'Could not evaluate the expression "$scope": Undefined variable $scope', + $exception->getMessage() + ); + } } } } diff --git a/tests/IsAServiceTraitTest.php b/tests/IsAServiceTraitTest.php index 9c86e0ce5..f2309a389 100644 --- a/tests/IsAServiceTraitTest.php +++ b/tests/IsAServiceTraitTest.php @@ -28,13 +28,22 @@ public function testThrowsAnExceptionWhenTryingToCloneInstance(): void clone new NotClonableDummy(); static::fail('Expected exception to be thrown.'); } catch (Throwable $exception) { - static::assertEquals( - 'Call to private Nelmio\Alice\NotClonableDummy::__clone() from context ' - .'\'Nelmio\Alice\IsAServiceTraitTest\'', - $exception->getMessage() - ); static::assertEquals(0, $exception->getCode()); static::assertNull($exception->getPrevious()); + + if (PHP_VERSION_ID < 80000) { + static::assertEquals( + 'Call to private Nelmio\Alice\NotClonableDummy::__clone() from context ' + . '\'Nelmio\Alice\IsAServiceTraitTest\'', + $exception->getMessage() + ); + } else { + static::assertEquals( + 'Call to private Nelmio\Alice\NotClonableDummy::__clone() from scope ' + . 'Nelmio\Alice\IsAServiceTraitTest', + $exception->getMessage() + ); + } } $dummyRefl = new ReflectionClass(NotClonableDummy::class); diff --git a/vendor-bin/infection/composer.json b/vendor-bin/infection/composer.json index 82389fffd..cfce244b8 100644 --- a/vendor-bin/infection/composer.json +++ b/vendor-bin/infection/composer.json @@ -1,6 +1,6 @@ { "require-dev": { - "infection/infection": "^0.16", + "infection/infection": "^0.20", "theofidry/composer-inheritance-plugin": "^1.0" }, "config": {