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
28 changes: 28 additions & 0 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1480,6 +1480,34 @@ jobs:
cd e2e/composer-no-versions
composer install
../../bin/phpstan analyze test.php --level=0
- script: |
# Scope::getPhpVersion() has to honour the composer.json "require.php" range:
# https://github.com/phpstan/phpstan/issues/15270
cd e2e/composer-php-version-range-7-and-8
composer install
OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse --no-progress --error-format raw")
echo "$OUTPUT"
../bashunit -a contains '/errors.php:11:Non-capturing catch is supported only on PHP 8.0 and later.' "$OUTPUT"
../bashunit -a contains '/errors.php:23:Named arguments are supported only on PHP 8.0 and later.' "$OUTPUT"
../bashunit -a contains '/errors.php:29:Function ComposerPhpVersionRange7And8Errors\phpdocBoolReturn() never returns false so the return type can be changed to true.' "$OUTPUT"
../bashunit -a not_contains 'no-errors.php' "$OUTPUT"
../bashunit -a not_contains 'php-version-id.php' "$OUTPUT"
- script: |
cd e2e/composer-php-version-range-7
composer install --ignore-platform-reqs
../../bin/phpstan analyse --no-progress
- script: |
cd e2e/composer-php-version-range-8-0
composer install
OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse --no-progress --error-format raw")
echo "$OUTPUT"
../bashunit -a contains '/errors.php:16:Missing parameter $j (int) in call to function ComposerPhpVersionRange80Errors\acceptsThreeInts.' "$OUTPUT"
../bashunit -a contains '/errors.php:16:Unpacked argument (...) cannot be followed by a non-unpacked argument.' "$OUTPUT"
../bashunit -a not_contains 'no-errors.php' "$OUTPUT"
- script: |
cd e2e/composer-php-version-range-8-5
composer install --ignore-platform-reqs
../../bin/phpstan analyse --no-progress
- script: |
cd e2e/composer-version-config-invalid
OUTPUT=$(../bashunit -a exit_code "1" ../../bin/phpstan)
Expand Down
2 changes: 2 additions & 0 deletions e2e/composer-php-version-range-7-and-8/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/vendor/
composer.lock
5 changes: 5 additions & 0 deletions e2e/composer-php-version-range-7-and-8/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"require": {
"php": "^7.4 || ^8.0"
}
}
40 changes: 40 additions & 0 deletions e2e/composer-php-version-range-7-and-8/errors.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php declare(strict_types = 1);

namespace ComposerPhpVersionRange7And8Errors;

use RuntimeException;

function noncapturingCatch(): void
{
try {
throw new RuntimeException('foo');
} catch (RuntimeException) {
echo 'failed';
}
}

function acceptsTwoInts(int $i, int $j): void
{
echo $i + $j;
}

function namedArguments(): void
{
acceptsTwoInts(i: 1, j: 2);
}

/**
* @return bool
*/
function phpdocBoolReturn()
{
return returnsTrue();
}

/**
* @return true
*/
function returnsTrue(): bool
{
return true;
}
30 changes: 30 additions & 0 deletions e2e/composer-php-version-range-7-and-8/no-errors.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php declare(strict_types = 1);

namespace ComposerPhpVersionRange7And8;

use RuntimeException;

function unusedCatchVariable(): void
{
try {
throw new RuntimeException('foo');
} catch (RuntimeException $e) {
// no "Catch variable $e is never read." - the variable cannot be dropped
// on PHP 7, which has no non-capturing catch
echo 'failed';
}
}

// no "can be changed to true" - the native true type does not exist before PHP 8.2
function nativeBoolReturn(): bool
{
return returnsTrue();
}

/**
* @return true
*/
function returnsTrue(): bool
{
return true;
}
22 changes: 22 additions & 0 deletions e2e/composer-php-version-range-7-and-8/php-version-id.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php declare(strict_types = 1);

namespace ComposerPhpVersionRange7And8PhpVersionId;

use RuntimeException;
use function PHPStan\Testing\assertType;

// composer.json requires "^7.4 || ^8.0", so the analysed PHP version spans
// PHP 7.4 - PHP 8.6 no matter which PHP version PHPStan itself runs on.
assertType('int<70400, 80699>', PHP_VERSION_ID);

if (PHP_VERSION_ID >= 80000) {
// an explicit PHP_VERSION_ID check still narrows the range further down
assertType('int<80000, 80699>', PHP_VERSION_ID);

try {
throw new RuntimeException('foo');
} catch (RuntimeException) {
// no "Non-capturing catch is supported only on PHP 8.0 and later."
echo 'failed';
}
}
9 changes: 9 additions & 0 deletions e2e/composer-php-version-range-7-and-8/phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
includes:
- ../../conf/bleedingEdge.neon

parameters:
level: 8
paths:
- errors.php
- no-errors.php
- php-version-id.php
2 changes: 2 additions & 0 deletions e2e/composer-php-version-range-7/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/vendor/
composer.lock
5 changes: 5 additions & 0 deletions e2e/composer-php-version-range-7/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"require": {
"php": "^7.4"
}
}
31 changes: 31 additions & 0 deletions e2e/composer-php-version-range-7/no-errors.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php declare(strict_types = 1);

namespace ComposerPhpVersionRange7;

use function PHPStan\Testing\assertType;

// composer.json requires "^7.4", so the analysed PHP version stays in the PHP 7.4 range
// no matter which PHP version PHPStan itself runs on.
assertType('int<70400, 70499>', PHP_VERSION_ID);

function variadicParameter(int ...$args): void
{
// without named arguments a variadic parameter can only be a list
assertType('list<int>', $args);
}

class Foo
{

// no "cannot be final as it is never overridden by other classes" -
// PHP 7 does not warn about final private methods
final private function finalPrivateMethod(): void
{
}

public function doFoo(): void
{
$this->finalPrivateMethod();
}

}
4 changes: 4 additions & 0 deletions e2e/composer-php-version-range-7/phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
parameters:
level: 8
paths:
- no-errors.php
2 changes: 2 additions & 0 deletions e2e/composer-php-version-range-8-0/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/vendor/
composer.lock
5 changes: 5 additions & 0 deletions e2e/composer-php-version-range-8-0/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"require": {
"php": "^8.0"
}
}
17 changes: 17 additions & 0 deletions e2e/composer-php-version-range-8-0/errors.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php declare(strict_types = 1);

namespace ComposerPhpVersionRange80Errors;

function acceptsThreeInts(int $i, int $j, int $k): void
{
echo $i + $j + $k;
}

/**
* @param list<int> $args
*/
function namedArgumentAfterUnpackedArgument(array $args): void
{
// a named argument after an unpacked one is only allowed since PHP 8.1
acceptsThreeInts(...$args, k: 3);
}
14 changes: 14 additions & 0 deletions e2e/composer-php-version-range-8-0/no-errors.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php declare(strict_types = 1);

namespace ComposerPhpVersionRange80;

use function PHPStan\Testing\assertType;

// composer.json requires "^8.0", so the analysed PHP version spans PHP 8.0 - PHP 8.6.
assertType('int<80000, 80699>', PHP_VERSION_ID);

function variadicParameter(int ...$args): void
{
// named arguments exist since PHP 8.0, so a variadic parameter is not always a list
assertType('array<int<0, max>|string, int>', $args);
}
5 changes: 5 additions & 0 deletions e2e/composer-php-version-range-8-0/phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
parameters:
level: 8
paths:
- errors.php
- no-errors.php
2 changes: 2 additions & 0 deletions e2e/composer-php-version-range-8-5/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/vendor/
composer.lock
5 changes: 5 additions & 0 deletions e2e/composer-php-version-range-8-5/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"require": {
"php": "^8.5"
}
}
15 changes: 15 additions & 0 deletions e2e/composer-php-version-range-8-5/no-errors.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php declare(strict_types = 1);

namespace ComposerPhpVersionRange85;

use function PHPStan\Testing\assertType;

// composer.json requires "^8.5", so the analysed PHP version spans PHP 8.5 - PHP 8.6.
assertType('int<80500, 80699>', PHP_VERSION_ID);

function iniGet(): void
{
assertType('string', ini_get('memory_limit'));
// the max_memory_limit ini setting only exists since PHP 8.5
assertType('string', ini_get('max_memory_limit'));
}
4 changes: 4 additions & 0 deletions e2e/composer-php-version-range-8-5/phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
parameters:
level: 8
paths:
- no-errors.php
8 changes: 4 additions & 4 deletions src/Analyser/DirectInternalScopeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use PHPStan\DependencyInjection\ExtensionsCollection;
use PHPStan\Node\Printer\ExprPrinter;
use PHPStan\Parser\Parser;
use PHPStan\Php\ConfiguredPhpVersionRangeHelper;
use PHPStan\Php\PhpVersion;
use PHPStan\Reflection\AttributeReflectionFactory;
use PHPStan\Reflection\InitializerExprTypeResolver;
Expand All @@ -24,7 +25,6 @@ final class DirectInternalScopeFactory implements InternalScopeFactory
private ExpressionResultStorageStack $expressionResultStorageStack;

/**
* @param int|array{min: int, max: int}|null $configPhpVersion
* @param callable(Node $node, Scope $scope): void|null $nodeCallback
* @param ExtensionsCollection<ExpressionTypeResolverExtension> $expressionTypeResolverExtensions
*/
Expand All @@ -39,7 +39,7 @@ public function __construct(
private Parser $parser,
private PhpVersion $phpVersion,
private AttributeReflectionFactory $attributeReflectionFactory,
private int|array|null $configPhpVersion,
private ConfiguredPhpVersionRangeHelper $configuredPhpVersionRangeHelper,
private $nodeCallback,
private ConstantResolver $constantResolver,
private bool $createsNodeCallbackScopes = false,
Expand Down Expand Up @@ -90,7 +90,7 @@ public function create(
$context,
$this->phpVersion,
$this->attributeReflectionFactory,
$this->configPhpVersion,
$this->configuredPhpVersionRangeHelper,
$this->nodeCallback,
$declareStrictTypes,
$function,
Expand Down Expand Up @@ -135,7 +135,7 @@ private function withFlavor(bool $createsNodeCallbackScopes): self
$this->parser,
$this->phpVersion,
$this->attributeReflectionFactory,
$this->configPhpVersion,
$this->configuredPhpVersionRangeHelper,
$this->nodeCallback,
$this->constantResolver,
$createsNodeCallbackScopes,
Expand Down
6 changes: 3 additions & 3 deletions src/Analyser/DirectInternalScopeFactoryFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PHPStan\DependencyInjection\ExtensionsCollection;
use PHPStan\Node\Printer\ExprPrinter;
use PHPStan\Parser\Parser;
use PHPStan\Php\ConfiguredPhpVersionRangeHelper;
use PHPStan\Php\PhpVersion;
use PHPStan\Reflection\AttributeReflectionFactory;
use PHPStan\Reflection\InitializerExprTypeResolver;
Expand All @@ -18,7 +19,6 @@ final class DirectInternalScopeFactoryFactory implements InternalScopeFactoryFac
{

/**
* @param int|array{min: int, max: int}|null $configPhpVersion
* @param ExtensionsCollection<ExpressionTypeResolverExtension> $expressionTypeResolverExtensions
*/
public function __construct(
Expand All @@ -32,7 +32,7 @@ public function __construct(
private Parser $parser,
private PhpVersion $phpVersion,
private AttributeReflectionFactory $attributeReflectionFactory,
private int|array|null $configPhpVersion,
private ConfiguredPhpVersionRangeHelper $configuredPhpVersionRangeHelper,
private ConstantResolver $constantResolver,
)
{
Expand All @@ -54,7 +54,7 @@ public function create(?callable $nodeCallback): DirectInternalScopeFactory
$this->parser,
$this->phpVersion,
$this->attributeReflectionFactory,
$this->configPhpVersion,
$this->configuredPhpVersionRangeHelper,
$nodeCallback,
$this->constantResolver,
);
Expand Down
Loading
Loading