diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml
new file mode 100644
index 00000000000..8f359728b50
--- /dev/null
+++ b/.github/workflows/bench.yml
@@ -0,0 +1,95 @@
+name: "Benchmark"
+
+on:
+ pull_request:
+ paths-ignore:
+ - 'compiler/**'
+ - 'apigen/**'
+ - 'changelog-generator/**'
+ - 'issue-bot/**'
+ push:
+ branches:
+ - "2.1.x"
+ paths-ignore:
+ - 'compiler/**'
+ - 'apigen/**'
+ - 'changelog-generator/**'
+ - 'issue-bot/**'
+
+concurrency:
+ group: bench-${{ github.head_ref || github.run_id }}
+ cancel-in-progress: true
+
+permissions:
+ contents: read
+
+jobs:
+ baseline:
+ name: "Baseline"
+ runs-on: ubuntu-latest
+ timeout-minutes: 60
+
+ steps:
+ - name: Harden the runner (Audit all outbound calls)
+ uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2
+ with:
+ egress-policy: audit
+
+ - name: "Checkout base branch"
+ uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
+
+ - name: "Install PHP"
+ uses: "shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1" # v2
+ with:
+ coverage: "none"
+ php-version: "8.5"
+ tools: pecl
+ extensions: ds,mbstring
+ ini-file: development
+ ini-values: memory_limit=-1
+
+ - uses: "ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520" # v3
+ - uses: "ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520" # v3
+ with:
+ working-directory: "tests/"
+
+ - name: "Run phpbench baseline"
+ run: "tests/vendor/bin/phpbench run --dump-file=tests/bench/storage/baseline.xml"
+
+ - name: "Upload baseline artifact"
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ with:
+ name: phpbench-baseline
+ path: tests/bench/storage/baseline.xml
+
+ test:
+ name: "Test"
+ runs-on: ubuntu-latest
+ timeout-minutes: 60
+
+ steps:
+ - name: Harden the runner (Audit all outbound calls)
+ uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2
+ with:
+ egress-policy: audit
+
+ - name: "Checkout"
+ uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
+
+ - name: "Install PHP"
+ uses: "shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1" # v2
+ with:
+ coverage: "none"
+ php-version: "8.5"
+ tools: pecl
+ extensions: ds,mbstring
+ ini-file: development
+ ini-values: memory_limit=-1
+
+ - uses: "ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520" # v3
+ - uses: "ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520" # v3
+ with:
+ working-directory: "tests/"
+
+ - name: "Run phpbench test"
+ run: "tests/vendor/bin/phpbench run --file=tests/bench/storage/baseline.xml --report=aggregate"
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 80474700d47..bdd01803733 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -259,7 +259,7 @@ jobs:
- name: "Downgrade PHPUnit with Paratest"
shell: bash
- run: "composer require --dev phpunit/phpunit:^9.6 brianium/paratest:^6.5 symfony/console:^5.4 symfony/process:^5.4 doctrine/instantiator:^1.0 --update-with-dependencies --ignore-platform-reqs --working-dir=tests"
+ run: "composer require --dev phpbench/phpbench:^1.2.15 phpunit/phpunit:^9.6 brianium/paratest:^6.5 symfony/console:^5.4 symfony/process:^5.4 doctrine/instantiator:^1.0 --update-with-dependencies --ignore-platform-reqs --working-dir=tests"
- uses: ./.github/actions/downgrade-code
with:
diff --git a/.gitignore b/.gitignore
index a1528dc2767..bb7d569b8d6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,4 @@
/tests/PHPStan/Reflection/data/golden/
tmp/.memory_limit
e2e/bashunit
+/.phpbench
diff --git a/Makefile b/Makefile
index 97eb28b4673..83fd04c81ab 100644
--- a/Makefile
+++ b/Makefile
@@ -14,6 +14,8 @@ tests-golden-reflection:
lint:
XDEBUG_MODE=off php vendor/bin/parallel-lint --colors \
--exclude tests/PHPStan/Analyser/data \
+ --exclude tests/bench/data \
+ --exclude tests/bench/RegressionBench.php \
--exclude tests/PHPStan/Analyser/nsrt \
--exclude tests/PHPStan/Rules/Methods/data \
--exclude tests/PHPStan/Rules/Functions/data \
diff --git a/build/phpstan.neon b/build/phpstan.neon
index 3469b8fca5a..526f68798d2 100644
--- a/build/phpstan.neon
+++ b/build/phpstan.neon
@@ -31,6 +31,7 @@ parameters:
- ../tests/PHPStan/Analyser/nsrt/*
- ../tests/PHPStan/Analyser/traits/*
- ../tests/notAutoloaded/*
+ - ../tests/bench/*
- ../tests/PHPStan/Reflection/UnionTypesTest.php
- ../tests/PHPStan/Reflection/MixedTypeTest.php
- ../tests/e2e/magic-setter/*
diff --git a/composer.json b/composer.json
index 7e853c5406e..f9e58c76daa 100644
--- a/composer.json
+++ b/composer.json
@@ -153,7 +153,8 @@
},
"classmap": [
"tests/e2e",
- "tests/PHPStan"
+ "tests/PHPStan",
+ "tests/bench"
]
},
"repositories": [
diff --git a/phpbench.json b/phpbench.json
new file mode 100644
index 00000000000..aa0b03f4724
--- /dev/null
+++ b/phpbench.json
@@ -0,0 +1,7 @@
+{
+ "$schema":"./tests/vendor/phpbench/phpbench/phpbench.schema.json",
+ "runner.bootstrap": "vendor/autoload.php",
+ "runner.path": "tests/bench",
+ "runner.file_pattern": "*Bench.php",
+ "storage.xml_storage_path": "tests/bench/storage"
+}
diff --git a/phpcs.xml b/phpcs.xml
index 3a6696fa3db..4d57743f555 100644
--- a/phpcs.xml
+++ b/phpcs.xml
@@ -53,7 +53,7 @@
src/Command/CommandHelper.php
- src/Testing/PHPStanTestCase.php
+ src/Testing/PHPStanTestCaseTrait.php
tests
@@ -65,6 +65,7 @@
+
diff --git a/src/Testing/PHPStanTestCase.php b/src/Testing/PHPStanTestCase.php
index 2532c300758..d85c4f3a5fa 100644
--- a/src/Testing/PHPStanTestCase.php
+++ b/src/Testing/PHPStanTestCase.php
@@ -8,14 +8,9 @@
use PHPStan\Analyser\ScopeFactory;
use PHPStan\Analyser\TypeSpecifier;
use PHPStan\BetterReflection\Reflector\Reflector;
-use PHPStan\DependencyInjection\Container;
-use PHPStan\DependencyInjection\ContainerFactory;
use PHPStan\DependencyInjection\Reflection\ClassReflectionExtensionRegistryProvider;
use PHPStan\DependencyInjection\Type\ExpressionTypeResolverExtensionRegistryProvider;
use PHPStan\DependencyInjection\Type\OperatorTypeSpecifyingExtensionRegistryProvider;
-use PHPStan\File\FileHelper;
-use PHPStan\Internal\DirectoryCreator;
-use PHPStan\Internal\DirectoryCreatorException;
use PHPStan\Node\Printer\ExprPrinter;
use PHPStan\Parser\Parser;
use PHPStan\Php\ComposerPhpVersionFactory;
@@ -32,76 +27,17 @@
use PHPStan\Type\UsefulTypeAliasResolver;
use PHPUnit\Framework\ExpectationFailedException;
use PHPUnit\Framework\TestCase;
-use function array_merge;
use function count;
-use function hash;
use function implode;
use function rtrim;
use function sprintf;
-use function sys_get_temp_dir;
use const DIRECTORY_SEPARATOR;
-use const PHP_VERSION_ID;
/** @api */
abstract class PHPStanTestCase extends TestCase
{
- /** @var array */
- private static array $containers = [];
-
- /** @api */
- public static function getContainer(): Container
- {
- $additionalConfigFiles = [__DIR__ . '/TestCase.neon'];
- foreach (static::getAdditionalConfigFiles() as $configFile) {
- $additionalConfigFiles[] = $configFile;
- }
- $cacheKey = hash('sha256', implode("\n", $additionalConfigFiles));
-
- if (!isset(self::$containers[$cacheKey])) {
- $tmpDir = sys_get_temp_dir() . '/phpstan-tests';
- try {
- DirectoryCreator::ensureDirectoryExists($tmpDir, 0777);
- } catch (DirectoryCreatorException $e) {
- self::fail($e->getMessage());
- }
-
- $rootDir = __DIR__ . '/../..';
- $fileHelper = new FileHelper($rootDir);
- $rootDir = $fileHelper->normalizePath($rootDir, '/');
- $containerFactory = new ContainerFactory($rootDir);
- $container = $containerFactory->create($tmpDir, array_merge([
- $containerFactory->getConfigDirectory() . '/config.level8.neon',
- ], $additionalConfigFiles), []);
- self::$containers[$cacheKey] = $container;
-
- foreach ($container->getParameter('bootstrapFiles') as $bootstrapFile) {
- (static function (string $file) use ($container): void {
- require_once $file;
- })($bootstrapFile);
- }
-
- if (PHP_VERSION_ID >= 80000) {
- require_once __DIR__ . '/../../stubs/runtime/Enum/UnitEnum.php';
- require_once __DIR__ . '/../../stubs/runtime/Enum/BackedEnum.php';
- require_once __DIR__ . '/../../stubs/runtime/Enum/ReflectionEnum.php';
- require_once __DIR__ . '/../../stubs/runtime/Enum/ReflectionEnumUnitCase.php';
- require_once __DIR__ . '/../../stubs/runtime/Enum/ReflectionEnumBackedCase.php';
- }
- } else {
- ContainerFactory::postInitializeContainer(self::$containers[$cacheKey]);
- }
-
- return self::$containers[$cacheKey];
- }
-
- /**
- * @return string[]
- */
- public static function getAdditionalConfigFiles(): array
- {
- return [];
- }
+ use PHPStanTestCaseTrait;
public static function getParser(): Parser
{
@@ -188,11 +124,6 @@ protected function shouldTreatPhpDocTypesAsCertain(): bool
return true;
}
- public static function getFileHelper(): FileHelper
- {
- return self::getContainer()->getByType(FileHelper::class);
- }
-
/**
* Provides a DIRECTORY_SEPARATOR agnostic assertion helper, to compare file paths.
*
diff --git a/src/Testing/PHPStanTestCaseTrait.php b/src/Testing/PHPStanTestCaseTrait.php
new file mode 100644
index 00000000000..49e4c6aef1c
--- /dev/null
+++ b/src/Testing/PHPStanTestCaseTrait.php
@@ -0,0 +1,81 @@
+ */
+ private static array $containers = [];
+
+ public static function getContainer(): Container
+ {
+ $additionalConfigFiles = [__DIR__ . '/TestCase.neon'];
+ foreach (static::getAdditionalConfigFiles() as $configFile) {
+ $additionalConfigFiles[] = $configFile;
+ }
+ $cacheKey = hash('sha256', implode("\n", $additionalConfigFiles));
+
+ if (!isset(self::$containers[$cacheKey])) {
+ $tmpDir = sys_get_temp_dir() . '/phpstan-tests';
+ try {
+ DirectoryCreator::ensureDirectoryExists($tmpDir, 0777);
+ } catch (DirectoryCreatorException $e) {
+ throw new RuntimeException($e->getMessage(), previous: $e);
+ }
+
+ $rootDir = __DIR__ . '/../..';
+ $fileHelper = new FileHelper($rootDir);
+ $rootDir = $fileHelper->normalizePath($rootDir, '/');
+ $containerFactory = new ContainerFactory($rootDir);
+ $container = $containerFactory->create($tmpDir, array_merge([
+ $containerFactory->getConfigDirectory() . '/config.level8.neon',
+ ], $additionalConfigFiles), []);
+ self::$containers[$cacheKey] = $container;
+
+ foreach ($container->getParameter('bootstrapFiles') as $bootstrapFile) {
+ (static function (string $file) use ($container): void {
+ require_once $file;
+ })($bootstrapFile);
+ }
+
+ if (PHP_VERSION_ID >= 80000) {
+ require_once __DIR__ . '/../../stubs/runtime/Enum/UnitEnum.php';
+ require_once __DIR__ . '/../../stubs/runtime/Enum/BackedEnum.php';
+ require_once __DIR__ . '/../../stubs/runtime/Enum/ReflectionEnum.php';
+ require_once __DIR__ . '/../../stubs/runtime/Enum/ReflectionEnumUnitCase.php';
+ require_once __DIR__ . '/../../stubs/runtime/Enum/ReflectionEnumBackedCase.php';
+ }
+ } else {
+ ContainerFactory::postInitializeContainer(self::$containers[$cacheKey]);
+ }
+
+ return self::$containers[$cacheKey];
+ }
+
+ /**
+ * @return string[]
+ */
+ public static function getAdditionalConfigFiles(): array
+ {
+ return [];
+ }
+
+ public static function getFileHelper(): FileHelper
+ {
+ return self::getContainer()->getByType(FileHelper::class);
+ }
+
+}
diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php
index 820338325d9..c74a1c3ff59 100644
--- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php
+++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php
@@ -157,6 +157,7 @@ public function testExtendsPdoStatementCrash(): void
public function testBug12803(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-12803.php');
$this->assertNoErrors($errors);
}
@@ -199,12 +200,14 @@ public function testPropertyAssignIntersectionStaticTypeBug(): void
public function testBug2823(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-2823.php');
$this->assertNoErrors($errors);
}
public function testBug13424(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-13424.php');
$this->assertCount(1, $errors);
$this->assertSame('Instantiated class Bug13424\Hello not found.', $errors[0]->getMessage());
@@ -237,14 +240,9 @@ public function testTwoSameClassesInSingleFile(): void
$this->assertSame(36, $error->getLine());
}
- public function testBug6936(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-6936.php');
- $this->assertNoErrors($errors);
- }
-
public function testBug3405(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-3405.php');
$this->assertCount(1, $errors);
$this->assertSame('Magic constant __TRAIT__ is always empty outside a trait.', $errors[0]->getMessage());
@@ -253,94 +251,78 @@ public function testBug3405(): void
public function testBug3415(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/../Rules/Methods/data/bug-3415.php');
$this->assertNoErrors($errors);
}
public function testBug3415Two(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/../Rules/Methods/data/bug-3415-2.php');
$this->assertNoErrors($errors);
}
public function testBug3468(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-3468.php');
$this->assertNoErrors($errors);
}
- public function testBug3686(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-3686.php');
- $this->assertNoErrors($errors);
- }
-
- #[RequiresPhp('>= 8.0')]
- public function testBug13352(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-13352.php');
- $this->assertNoErrors($errors);
- }
-
public function testBug3379(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/nsrt/bug-3379.php');
$this->assertCount(1, $errors);
$this->assertSame('Constant SOME_UNKNOWN_CONST not found.', $errors[0]->getMessage());
}
- public function testBug13685(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-13685.php');
- $this->assertNoErrors($errors);
- }
-
public function testBug3798(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-3798.php');
$this->assertNoErrors($errors);
}
public function testBug3909(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-3909.php');
$this->assertNoErrors($errors);
}
public function testBug4097(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-4097.php');
$this->assertNoErrors($errors);
}
- public function testBug4300(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-4300.php');
- $this->assertCount(1, $errors);
- $this->assertSame('Comparison operation ">" between 0 and 0 is always false.', $errors[0]->getMessage());
- $this->assertSame(13, $errors[0]->getLine());
- }
-
public function testBug4513(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-4513.php');
$this->assertNoErrors($errors);
}
public function testBug1871(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-1871.php');
$this->assertNoErrors($errors);
}
public function testBug3309(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-3309.php');
$this->assertNoErrors($errors);
}
public function testBug11649(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-11649.php');
$this->assertNoErrors($errors);
}
@@ -348,12 +330,14 @@ public function testBug11649(): void
#[RequiresPhp('>= 8.0')]
public function testBug6872(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6872.php');
$this->assertNoErrors($errors);
}
public function testBug3769(): void
{
+ // false positive
require_once __DIR__ . '/../Rules/Generics/data/bug-3769.php';
$errors = $this->runAnalyse(__DIR__ . '/../Rules/Generics/data/bug-3769.php');
$this->assertNoErrors($errors);
@@ -361,6 +345,7 @@ public function testBug3769(): void
public function testBug6301(): void
{
+ // false positive
require_once __DIR__ . '/../Rules/Generics/data/bug-6301.php';
$errors = $this->runAnalyse(__DIR__ . '/../Rules/Generics/data/bug-6301.php');
$this->assertNoErrors($errors);
@@ -368,18 +353,21 @@ public function testBug6301(): void
public function testBug3922(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-3922-integration.php');
$this->assertNoErrors($errors);
}
public function testBug1843(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-1843.php');
$this->assertNoErrors($errors);
}
public function testBug9711(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-9711.php');
$this->assertCount(1, $errors);
$this->assertSame('Function in_array invoked with 1 parameter, 2-3 required.', $errors[0]->getMessage());
@@ -387,6 +375,7 @@ public function testBug9711(): void
public function testBug4713(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-4713.php');
$this->assertCount(1, $errors);
$this->assertSame('Method Bug4713\Service::createInstance() should return Bug4713\Service but returns object.', $errors[0]->getMessage());
@@ -401,6 +390,7 @@ public function testBug4713(): void
public function testBug4288(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-4288.php');
$this->assertNoErrors($errors);
@@ -423,6 +413,7 @@ public function testBug4288(): void
public function testBug4702(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-4702.php');
$this->assertNoErrors($errors);
}
@@ -430,6 +421,7 @@ public function testBug4702(): void
#[RequiresPhp('>= 8.1')]
public function testBug14100(): void
{
+ // false negative
$errors = $this->runAnalyse(__DIR__ . '/data/bug-14100.php');
$this->assertNoErrors($errors);
}
@@ -448,6 +440,7 @@ public function testFunctionThatExistsOn72AndLater(): void
public function testBug4715(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-4715.php');
$this->assertNoErrors($errors);
}
@@ -455,6 +448,7 @@ public function testBug4715(): void
#[RequiresPhp('>= 8.2')]
public function testBug4734(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-4734.php');
$this->assertCount(5, $errors); // could be 3
@@ -465,52 +459,38 @@ public function testBug4734(): void
$this->assertSame('Access to an undefined property Bug4734\Foo::$httpMethodParameterOverride4.', $errors[4]->getMessage());
}
- public function testBug5231(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-5231.php');
- $this->assertNotEmpty($errors);
- }
-
- public function testBug5231Two(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-5231_2.php');
- $this->assertNotEmpty($errors);
- }
-
#[RequiresPhp('>= 8.1')]
public function testBug12512(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-12512.php');
$this->assertNoErrors($errors);
}
- #[RequiresPhp('>= 8.0')]
- public function testBug13218(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-13218.php');
- $this->assertNoErrors($errors);
- }
-
public function testBug5529(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/nsrt/bug-5529.php');
$this->assertNoErrors($errors);
}
public function testBug5527(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-5527.php');
$this->assertNoErrors($errors);
}
public function testBug5639(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-5639.php');
$this->assertNoErrors($errors);
}
public function testBug5657(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-5657.php');
$this->assertNoErrors($errors);
}
@@ -518,6 +498,7 @@ public function testBug5657(): void
#[RequiresPhp('>= 8.0')]
public function testBug5951(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-5951.php');
$this->assertNoErrors($errors);
}
@@ -537,12 +518,14 @@ public function testEnums(): void
public function testBug6255(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6255.php');
$this->assertNoErrors($errors);
}
public function testBug6300(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6300.php');
$this->assertCount(1, $errors);
$this->assertSame('Call to an undefined method Bug6300\Bar::get().', $errors[0]->getMessage());
@@ -551,6 +534,7 @@ public function testBug6300(): void
public function testBug6466(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6466.php');
$this->assertNoErrors($errors);
}
@@ -558,12 +542,14 @@ public function testBug6466(): void
#[RequiresPhp('>= 8.1')]
public function testBug6494(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6494.php');
$this->assertNoErrors($errors);
}
public function testBug6253(): void
{
+ // false positive
$errors = $this->runAnalyse(
__DIR__ . '/data/bug-6253.php',
[
@@ -575,30 +561,23 @@ public function testBug6253(): void
$this->assertNoErrors($errors);
}
- public function testBug6442(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-6442.php');
- $this->assertCount(2, $errors);
- $this->assertSame('Dumped type: \'Bug6442\\\B\'', $errors[0]->getMessage());
- $this->assertSame(9, $errors[0]->getLine());
- $this->assertSame('Dumped type: \'Bug6442\\\A\'', $errors[1]->getMessage());
- $this->assertSame(9, $errors[1]->getLine());
- }
-
public function testBug13057(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-13057.php');
$this->assertNoErrors($errors);
}
public function testBug6375(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6375.php');
$this->assertNoErrors($errors);
}
public function testBug6501(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6501.php');
$this->assertCount(1, $errors);
$this->assertSame('PHPDoc tag @var with type R of Exception|stdClass is not subtype of native type stdClass.', $errors[0]->getMessage());
@@ -608,48 +587,56 @@ public function testBug6501(): void
#[RequiresPhp('>= 8.0')]
public function testBug6114(): void
{
+ // false negative
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6114.php');
$this->assertNoErrors($errors);
}
public function testBug6681(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6681.php');
$this->assertNoErrors($errors);
}
public function testBug6212(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6212.php');
$this->assertNoErrors($errors);
}
public function testBug6740(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6740-b.php');
$this->assertNoErrors($errors);
}
public function testBug6866(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6866.php');
$this->assertNoErrors($errors);
}
public function testBug6649(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6649.php');
$this->assertNoErrors($errors);
}
public function testBug12778(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-12778.php');
$this->assertNoErrors($errors);
}
public function testBug6842(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6842.php');
$this->assertCount(2, $errors);
$this->assertSame('Generator expects value type T of DateTimeInterface, DateTime|DateTimeImmutable|T of DateTimeInterface given.', $errors[0]->getMessage());
@@ -662,6 +649,7 @@ public function testBug6842(): void
#[RequiresPhp('>= 8.0')]
public function testBug6896(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6896.php');
$this->assertCount(4, $errors);
$this->assertSame('Generic type IteratorIterator<(int|string), mixed> in PHPDoc tag @return does not specify all template types of class IteratorIterator: TKey, TValue, TIterator', $errors[0]->getMessage());
@@ -676,45 +664,23 @@ public function testBug6896(): void
public function testBug6940(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6940.php');
$this->assertCount(1, $errors);
$this->assertSame('Loose comparison using == between array{} and array{} will always evaluate to true.', $errors[0]->getMessage());
$this->assertSame(12, $errors[0]->getLine());
}
- public function testBug1447(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-1447.php');
- $this->assertNoErrors($errors);
- }
-
- public function testBug5081(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-5081.php');
- $this->assertNoErrors($errors);
- }
-
- public function testBug1388(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-1388.php');
- $this->assertNoErrors($errors);
- }
-
- #[RequiresPhp('>= 8.0')]
- public function testBug4308(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-4308.php');
- $this->assertNoErrors($errors);
- }
-
public function testBug4732(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-4732.php');
$this->assertNoErrors($errors);
}
public function testBug6160(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6160.php');
$this->assertCount(2, $errors);
$this->assertSame('Parameter #1 $flags of static method Bug6160\HelloWorld::split() expects 0|1|2, 94561 given.', $errors[0]->getMessage());
@@ -725,12 +691,14 @@ public function testBug6160(): void
public function testBug6979(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6979.php');
$this->assertNoErrors($errors);
}
public function testBug7030(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7030.php');
$this->assertCount(1, $errors);
$this->assertSame('PHPDoc tag @method has invalid value (array getItemsForID($id, $quantity, $shippingPostCode = null, $wholesalerList = null, $shippingLatitude =
@@ -740,6 +708,7 @@ public function testBug7030(): void
#[RequiresPhp('>= 8.1')]
public function testBug7012(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7012.php');
$this->assertNoErrors($errors);
}
@@ -747,12 +716,14 @@ public function testBug7012(): void
#[RequiresPhp('>= 8.1')]
public function testBug6192(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6192.php');
$this->assertNoErrors($errors);
}
public function testBug7068(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/nsrt/bug-7068.php');
$this->assertNoErrors($errors);
}
@@ -767,6 +738,7 @@ public function testDiscussion6993(): void
public function testBug7077(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7077.php');
$this->assertNoErrors($errors);
}
@@ -774,6 +746,7 @@ public function testBug7077(): void
#[RequiresPhp('>= 8.0')]
public function testBug7078(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/nsrt/bug-7078.php');
$this->assertNoErrors($errors);
}
@@ -781,12 +754,14 @@ public function testBug7078(): void
#[RequiresPhp('>= 8.0')]
public function testBug7116(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7116.php');
$this->assertNoErrors($errors);
}
public function testBug3853(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/nsrt/bug-3853.php');
$this->assertNoErrors($errors);
}
@@ -794,6 +769,7 @@ public function testBug3853(): void
#[RequiresPhp('>= 8.1')]
public function testBug7135(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7135.php');
$this->assertCount(1, $errors);
$this->assertSame('Cannot create callable from the new operator.', $errors[0]->getMessage());
@@ -814,16 +790,9 @@ public function testDiscussion7124(): void
$this->assertSame(59, $errors[3]->getLine());
}
- public function testBug7214(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-7214.php');
- $this->assertCount(1, $errors);
- $this->assertSame('Method Bug7214\HelloWorld::getFoo() has no return type specified.', $errors[0]->getMessage());
- $this->assertSame(6, $errors[0]->getLine());
- }
-
public function testBug12327(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-12327.php');
$this->assertCount(1, $errors);
@@ -833,12 +802,14 @@ public function testBug12327(): void
public function testBug7215(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7215.php');
$this->assertNoErrors($errors);
}
public function testBug7094(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7094.php');
$this->assertCount(6, $errors);
@@ -880,42 +851,49 @@ public function testUnresolvableParameter(): void
public function testBug7248(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7248.php');
$this->assertNoErrors($errors);
}
public function testBug7351(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7351.php');
$this->assertNoErrors($errors);
}
public function testBug7381(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7381.php');
$this->assertNoErrors($errors);
}
public function testBug7153(): void
{
+ // false negative
$errors = $this->runAnalyse(__DIR__ . '/nsrt/bug-7153.php');
$this->assertNoErrors($errors);
}
public function testBug7275(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7275.php');
$this->assertNoErrors($errors);
}
public function testBug7500(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7500.php');
$this->assertNoErrors($errors);
}
public function testBug12767(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-12767.php');
$this->assertCount(3, $errors);
@@ -926,6 +904,7 @@ public function testBug12767(): void
public function testBug7554(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7554.php');
$this->assertCount(2, $errors);
@@ -936,35 +915,16 @@ public function testBug7554(): void
$this->assertSame(27, $errors[1]->getLine());
}
- public function testBug7637(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-7637.php');
- $this->assertCount(3, $errors);
-
- $this->assertSame('Method Bug7637\HelloWorld::getProperty() has invalid return type Bug7637\rex_backend_login.', $errors[0]->getMessage());
- $this->assertSame(54, $errors[0]->getLine());
-
- $this->assertSame('Method Bug7637\HelloWorld::getProperty() has invalid return type Bug7637\rex_timer.', $errors[1]->getMessage());
- $this->assertSame(54, $errors[1]->getLine());
-
- $this->assertSame('Call to function is_string() with string will always evaluate to true.', $errors[2]->getMessage());
- $this->assertSame(57, $errors[2]->getLine());
- }
-
- public function testBug12671(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-12671.php');
- $this->assertNoErrors($errors);
- }
-
public function testBug7737(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7737.php');
$this->assertNoErrors($errors);
}
public function testBug7762(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7762.php');
$this->assertCount(2, $errors);
$this->assertSame('Function json_decode invoked with 0 parameters, 1-4 required.', $errors[0]->getMessage());
@@ -983,62 +943,36 @@ public function testPrestashopInfiniteRunXmlLoaderBug(): void
public function testBug7320(): void
{
+ // false negative
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7320.php');
$this->assertCount(1, $errors);
$this->assertSame('Parameter #1 $c of function Bug7320\foo expects callable(int=): void, Closure(int): void given.', $errors[0]->getMessage());
$this->assertSame(13, $errors[0]->getLine());
}
- public function testBug7581(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-7581.php');
- $this->assertNoErrors($errors);
- }
-
- public function testBug7903(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-7903.php');
- $this->assertCount(39, $errors);
- }
-
- public function testBug7901(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-7901.php');
- $this->assertNoErrors($errors);
- }
-
public function testBug7918(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7918.php');
$this->assertNoErrors($errors);
}
- public function testBug7140(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-7140.php');
- $this->assertNoErrors($errors);
- }
-
public function testArrayUnion(): void
{
$errors = $this->runAnalyse(__DIR__ . '/data/array-union.php');
$this->assertNoErrors($errors);
}
- public function testBug6948(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-6948.php');
- $this->assertNoErrors($errors);
- }
-
public function testBug7963(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7963.php');
$this->assertNoErrors($errors);
}
public function testBug7963Two(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7963-two.php');
$this->assertNoErrors($errors);
}
@@ -1046,6 +980,7 @@ public function testBug7963Two(): void
#[RequiresPhp('>= 8.1')]
public function testBug8078(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-8078.php');
$this->assertNoErrors($errors);
}
@@ -1053,12 +988,14 @@ public function testBug8078(): void
#[RequiresPhp('>= 8.1')]
public function testBug8072(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-8072.php');
$this->assertNoErrors($errors);
}
public function testBug7787(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7787.php');
$this->assertCount(1, $errors);
$this->assertSame('Reflection error: Circular reference to class "Bug7787\TestClass"', $errors[0]->getMessage());
@@ -1066,6 +1003,7 @@ public function testBug7787(): void
public function testBug3865(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-3865.php');
$this->assertCount(1, $errors);
$this->assertSame('The @extends tag of class Bug3865\RecursiveClass describes Bug3865\RecursiveClass but the class extends Bug3865\EntityRepository.', $errors[0]->getMessage());
@@ -1074,6 +1012,7 @@ public function testBug3865(): void
public function testBug5312(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-5312.php');
$this->assertCount(5, $errors);
$this->assertSame('PHPDoc tag @template T for interface Bug5312\Updatable has invalid bound type Bug5312\T.', $errors[0]->getMessage());
@@ -1088,20 +1027,9 @@ public function testBug5312(): void
$this->assertSame(13, $errors[4]->getLine());
}
- public function testBug5390(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-5390.php');
- $this->assertCount(3, $errors);
- $this->assertSame('Property Bug5390\A::$b is never written, only read.', $errors[0]->getMessage());
- $this->assertSame(9, $errors[0]->getLine());
- $this->assertSame('Method Bug5390\A::infiniteRecursion() has no return type specified.', $errors[1]->getMessage());
- $this->assertSame(11, $errors[1]->getLine());
- $this->assertSame('Call to an undefined method Bug5390\B::someMethod().', $errors[2]->getMessage());
- $this->assertSame(12, $errors[2]->getLine());
- }
-
public function testBug7110(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7110.php');
$this->assertCount(1, $errors);
$this->assertSame('Parameter #1 $s of function Bug7110\takesInt expects int, string given.', $errors[0]->getMessage());
@@ -1110,6 +1038,7 @@ public function testBug7110(): void
public function testBug8376(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-8376.php');
$this->assertNoErrors($errors);
}
@@ -1129,47 +1058,24 @@ public function testAssertDocblock(): void
$this->assertSame(238, $errors[3]->getLine());
}
- #[RequiresPhp('>= 8.0')]
- public function testBug8147(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-8147.php');
- $this->assertNoErrors($errors);
- }
-
#[RequiresPhp('>= 8.0')]
public function testBug12934(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-12934.php');
$this->assertNoErrors($errors);
}
- public function testConditionalExpressionInfiniteLoop(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/conditional-expression-infinite-loop.php');
- $this->assertNoErrors($errors);
- }
-
public function testPr2030(): void
{
$errors = $this->runAnalyse(__DIR__ . '/data/pr-2030.php');
$this->assertNoErrors($errors);
}
- public function testBug6265(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-6265.php');
- $this->assertNotEmpty($errors);
- }
-
- public function testBug8503(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-8503.php');
- $this->assertNoErrors($errors);
- }
-
#[RequiresPhp('>= 8.0')]
public function testBug8537(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-8537.php');
$this->assertNoErrors($errors);
}
@@ -1177,30 +1083,13 @@ public function testBug8537(): void
#[RequiresPhp('>= 8.1')]
public function testBug7927(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7927.php');
$this->assertCount(2, $errors);
$this->assertSame('Enum case Bug7927\Test::One does not have a value but the enum is backed with the "int" type.', $errors[0]->getMessage());
$this->assertSame('Enum case Bug7927\Test::Two does not have a value but the enum is backed with the "int" type.', $errors[1]->getMessage());
}
- public function testBug8146(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-8146b.php');
- $this->assertNoErrors($errors);
- }
-
- public function testBug8215(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-8215.php');
- $this->assertNoErrors($errors);
- }
-
- public function testBug8146a(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-8146a.php');
- $this->assertNoErrors($errors);
- }
-
public static function getAdditionalConfigFiles(): array
{
return [
@@ -1210,6 +1099,7 @@ public static function getAdditionalConfigFiles(): array
public function testBug8004(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-8004.php');
$this->assertCount(2, $errors);
$this->assertSame('Strict comparison using !== between null and DateTimeInterface|string will always evaluate to true.', $errors[0]->getMessage());
@@ -1229,30 +1119,35 @@ public function testSkipCheckNoGenericClasses(): void
#[RequiresPhp('>= 8.1')]
public function testBug8983(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-8983.php');
$this->assertNoErrors($errors);
}
public function testBug9008(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-9008.php');
$this->assertNoErrors($errors);
}
public function testBug5091(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-5091.php');
$this->assertNoErrors($errors);
}
public function testBug13507(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-13507.php');
$this->assertNoErrors($errors);
}
public function testBug9459(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-9459.php');
$this->assertCount(1, $errors);
$this->assertSame('PHPDoc tag @var with type callable(): array is not subtype of native type Closure(): array{}.', $errors[0]->getMessage());
@@ -1260,12 +1155,14 @@ public function testBug9459(): void
public function testBug9573(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-9573.php');
$this->assertNoErrors($errors);
}
public function testBug13978(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-13978.php');
$this->assertNoErrors($errors);
}
@@ -1278,6 +1175,7 @@ public function testDiscussion13979(): void
public function testBug9039(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-9039.php');
$this->assertCount(1, $errors);
$this->assertSame('Constant Bug9039\Test::RULES is unused.', $errors[0]->getMessage());
@@ -1292,29 +1190,19 @@ public function testDiscussion9053(): void
public function testBug13492(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-13492.php');
$this->assertNoErrors($errors);
}
- public function testProcessCalledMethodInfiniteLoop(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/process-called-method-infinite-loop.php');
- $this->assertNoErrors($errors);
- }
-
#[RequiresPhp('>= 8.0')]
public function testBug9428(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-9428.php');
$this->assertNoErrors($errors);
}
- public function testBug9690(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-9690.php');
- $this->assertNoErrors($errors);
- }
-
public function testIgnoreIdentifiers(): void
{
$errors = $this->runAnalyse(__DIR__ . '/data/ignore-identifiers.php');
@@ -1339,6 +1227,7 @@ public function testIgnoreIdentifiers(): void
#[RequiresPhp('>= 8.1')]
public function testBug9994(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-9994.php');
$this->assertCount(2, $errors);
$this->assertSame('Negated boolean expression is always false.', $errors[0]->getMessage());
@@ -1348,12 +1237,14 @@ public function testBug9994(): void
#[RequiresPhp('>= 8.1')]
public function testBug13987(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-13987.php');
$this->assertNoErrors($errors);
}
public function testBug13982(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-13982.php');
$this->assertNoErrors($errors);
}
@@ -1361,6 +1252,7 @@ public function testBug13982(): void
#[RequiresPhp('>= 8.1')]
public function testBug10049(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-10049-recursive.php');
$this->assertCount(4, $errors);
$this->assertSame('PHPDoc tag @template for class Bug10049Recursive\SimpleEntity cannot have existing class Bug10049Recursive\SimpleEntity as its name.', $errors[0]->getMessage());
@@ -1376,25 +1268,22 @@ public function testBug10049(): void
#[RequiresPhp('>= 8.0')]
public function testBug10086(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-10086.php');
$this->assertNoErrors($errors);
}
- public function testBug10147(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-10147.php');
- $this->assertNoErrors($errors);
- }
-
#[RequiresPhp('>= 8.2')]
public function testBug10302(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-10302.php');
$this->assertNoErrors($errors);
}
public function testBug10358(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-10358.php');
$this->assertCount(1, $errors);
$this->assertSame('Cannot use Ns\Foo2 as Foo because the name is already in use', $errors[0]->getMessage());
@@ -1403,96 +1292,63 @@ public function testBug10358(): void
public function testBug10509(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-10509.php');
$this->assertCount(2, $errors);
$this->assertSame('Method Bug10509\Foo::doFoo() has no return type specified.', $errors[0]->getMessage());
$this->assertSame('PHPDoc tag @return contains unresolvable type.', $errors[1]->getMessage());
}
- public function testBug10538(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-10538.php');
- $this->assertNoErrors($errors);
- }
-
#[RequiresPhp('>= 8.1')]
public function testBug10847(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-10847.php');
$this->assertNoErrors($errors);
}
- #[RequiresPhp('>= 8.1')]
- public function testBug10772(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-10772.php');
- $this->assertNoErrors($errors);
- }
-
#[RequiresPhp('>= 8.1')]
public function testBug10985(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-10985.php');
$this->assertNoErrors($errors);
}
- #[RequiresPhp('>= 8.1')]
- public function testBug10979(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-10979.php');
- $this->assertNoErrors($errors);
- }
-
public function testBug11026(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-11026.php');
$this->assertNoErrors($errors);
}
public function testBug10867(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-10867.php');
$this->assertNoErrors($errors);
}
- #[RequiresPhp('>= 8.1')]
- public function testBug11263(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-11263.php');
- $this->assertNoErrors($errors);
- }
-
#[RequiresPhp('>= 8.0')]
public function testBug11147(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-11147.php');
$this->assertCount(1, $errors);
$this->assertSame('Method Bug11147\RedisAdapter::createConnection() has invalid return type Bug11147\NonExistentClass.', $errors[0]->getMessage());
}
- #[RequiresPhp('>= 8.0')]
- public function testBug11283(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-11283.php');
- $this->assertNoErrors($errors);
- }
-
public function testBug11292(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-11292.php');
$this->assertNoErrors($errors);
}
- #[RequiresPhp('>= 8.1')]
- public function testBug11297(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-11297.php');
- $this->assertNoErrors($errors);
- }
-
#[RequiresPhp('>= 8.0')]
public function testBug5597(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-5597.php');
$this->assertNoErrors($errors);
}
@@ -1500,6 +1356,7 @@ public function testBug5597(): void
#[RequiresPhp('>= 8.0')]
public function testBug11511(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-11511.php');
$this->assertCount(1, $errors);
$this->assertSame('Access to an undefined property object::$bar.', $errors[0]->getMessage());
@@ -1507,18 +1364,21 @@ public function testBug11511(): void
public function testBug12214(): void
{
+ // false negative
$errors = $this->runAnalyse(__DIR__ . '/data/bug-12214.php');
$this->assertNoErrors($errors);
}
public function testBug11598(): void
{
+ // false negative
$errors = $this->runAnalyse(__DIR__ . '/data/bug-11598.php');
$this->assertNoErrors($errors);
}
public function testBug11640(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-11640.php');
$this->assertNoErrors($errors);
}
@@ -1526,51 +1386,30 @@ public function testBug11640(): void
#[RequiresPhp('>= 8.0')]
public function testBug11709(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-11709.php');
$this->assertNoErrors($errors);
}
- public function testBug11913(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-11913.php');
- $this->assertNoErrors($errors);
- }
-
#[RequiresPhp('>= 8.3')]
public function testBug12549(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-12549.php');
$this->assertNoErrors($errors);
}
public function testBug12627(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-12627.php');
$this->assertNoErrors($errors);
}
- #[RequiresPhp('>= 8.3')]
- public function testBug12159(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-12159.php');
- $this->assertNoErrors($errors);
- }
-
- public function testBug12787(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-12787.php');
- $this->assertNoErrors($errors);
- }
-
- public function testBug12800(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-12800.php');
- $this->assertNoErrors($errors);
- }
-
#[RequiresPhp('>= 8.3')]
public function testBug12949(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-12949.php');
$this->assertCount(3, $errors);
$this->assertSame('Call to an undefined method object::0().', $errors[0]->getMessage());
@@ -1580,34 +1419,29 @@ public function testBug12949(): void
public function testBug12979(): void
{
+ // false negative
$errors = $this->runAnalyse(__DIR__ . '/data/bug-12979.php');
$this->assertNoErrors($errors);
}
public function testBug12095(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-12095.php');
$this->assertNoErrors($errors);
}
public function testBug13279(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-13279.php');
$this->assertCount(1, $errors);
$this->assertSame('Parameter #2 $offset of function array_splice expects int, string given.', $errors[0]->getMessage());
}
- public function testBug13310(): void
- {
- // require file to make sure the defined function is known
- require_once __DIR__ . '/data/bug-13310.php';
-
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-13310.php');
- $this->assertNoErrors($errors);
- }
-
public function testBug13714(): void
{
+ // crash
$errors = $this->runAnalyse(__DIR__ . '/data/bug-13714.php');
$this->assertCount(7, $errors);
$this->assertSame('Function Bug13714\curl_setopt invoked with 3 parameters, 0 required.', $errors[0]->getMessage());
@@ -1619,39 +1453,24 @@ public function testBug13714(): void
$this->assertSame('Function Bug13714\array_find invoked with 2 parameters, 0 required.', $errors[6]->getMessage());
}
- public function testBug13933(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-13933.php');
- $this->assertNoErrors($errors);
- }
-
#[RequiresPhp('>= 8.4')]
public function testBug13980(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-13980.php');
$this->assertNoErrors($errors);
}
- public function testBug14207(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-14207.php');
- $this->assertNoErrors($errors);
- }
-
- public function testBug14207And(): void
- {
- $errors = $this->runAnalyse(__DIR__ . '/data/bug-14207-and.php');
- $this->assertNoErrors($errors);
- }
-
public function testBug13945(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-13945.php');
$this->assertNoErrors($errors);
}
public function testBug13945Two(): void
{
+ // false positive
$errors = $this->runAnalyse(__DIR__ . '/data/bug-13945-2.php');
$this->assertNoErrors($errors);
}
diff --git a/tests/bench/BenchCase.php b/tests/bench/BenchCase.php
new file mode 100644
index 00000000000..8f94d3bb89a
--- /dev/null
+++ b/tests/bench/BenchCase.php
@@ -0,0 +1,32 @@
+
+ */
+ protected function runAnalyse(string $file, ?array $allAnalysedFiles = null): array
+ {
+ $file = self::getFileHelper()->normalizePath($file);
+
+ $analyser = self::getContainer()->getByType(Analyser::class);
+ $finalizer = self::getContainer()->getByType(AnalyserResultFinalizer::class);
+ return $finalizer->finalize(
+ $analyser->analyse([$file], null, null, true, $allAnalysedFiles),
+ false,
+ true,
+ )->getErrors();
+ }
+
+}
diff --git a/tests/bench/RegressionBench.php b/tests/bench/RegressionBench.php
new file mode 100644
index 00000000000..6998eea56e5
--- /dev/null
+++ b/tests/bench/RegressionBench.php
@@ -0,0 +1,49 @@
+= 100 milliseconds and mode(baseline.time.avg) < 500 milliseconds and mode(variant.time.avg) < mode(baseline.time.avg) +/- 25%)
+ or (mode(baseline.time.avg) >= 500 milliseconds and mode(variant.time.avg) < mode(baseline.time.avg) +/- 5%)')]
+class RegressionBench extends BenchCase
+{
+
+ /**
+ * @param array{string} $params
+ */
+ #[Bench\ParamProviders(['provideFiles'])]
+ public function benchRunAnalyse(array $params): void
+ {
+ $this->runAnalyse($params[0]);
+ }
+
+ /**
+ * @return iterable
+ */
+ public function provideFiles(): iterable
+ {
+ yield from self::findTestDataFilesFromDirectory(__DIR__ . '/data');
+ }
+
+ private static function findTestDataFilesFromDirectory(string $directory): array
+ {
+ $finder = new Finder();
+ $finder->followLinks();
+ $finder->sortByName(true);
+ $files = [];
+ foreach ($finder->files()->name('*.php')->in($directory) as $fileInfo) {
+ $files[$fileInfo->getBasename()] = [$fileInfo->getPathname()];
+ }
+
+ return $files;
+ }
+
+}
diff --git a/tests/PHPStan/Analyser/data/bug-10147.php b/tests/bench/data/bug-10147.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-10147.php
rename to tests/bench/data/bug-10147.php
diff --git a/tests/PHPStan/Analyser/data/bug-10538.php b/tests/bench/data/bug-10538.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-10538.php
rename to tests/bench/data/bug-10538.php
diff --git a/tests/PHPStan/Analyser/data/bug-10772.php b/tests/bench/data/bug-10772.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-10772.php
rename to tests/bench/data/bug-10772.php
diff --git a/tests/PHPStan/Analyser/data/bug-10979.php b/tests/bench/data/bug-10979.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-10979.php
rename to tests/bench/data/bug-10979.php
diff --git a/tests/PHPStan/Analyser/data/bug-11263.php b/tests/bench/data/bug-11263.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-11263.php
rename to tests/bench/data/bug-11263.php
diff --git a/tests/PHPStan/Analyser/data/bug-11283.php b/tests/bench/data/bug-11283.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-11283.php
rename to tests/bench/data/bug-11283.php
diff --git a/tests/PHPStan/Analyser/data/bug-11297.php b/tests/bench/data/bug-11297.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-11297.php
rename to tests/bench/data/bug-11297.php
diff --git a/tests/PHPStan/Analyser/data/bug-11913.php b/tests/bench/data/bug-11913.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-11913.php
rename to tests/bench/data/bug-11913.php
diff --git a/tests/PHPStan/Analyser/data/bug-12159.php b/tests/bench/data/bug-12159.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-12159.php
rename to tests/bench/data/bug-12159.php
diff --git a/tests/PHPStan/Analyser/data/bug-12671.php b/tests/bench/data/bug-12671.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-12671.php
rename to tests/bench/data/bug-12671.php
diff --git a/tests/PHPStan/Analyser/data/bug-12787.php b/tests/bench/data/bug-12787.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-12787.php
rename to tests/bench/data/bug-12787.php
diff --git a/tests/PHPStan/Analyser/data/bug-12800.php b/tests/bench/data/bug-12800.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-12800.php
rename to tests/bench/data/bug-12800.php
diff --git a/tests/PHPStan/Analyser/data/bug-13218.php b/tests/bench/data/bug-13218.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-13218.php
rename to tests/bench/data/bug-13218.php
diff --git a/tests/PHPStan/Analyser/data/bug-13310.php b/tests/bench/data/bug-13310.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-13310.php
rename to tests/bench/data/bug-13310.php
diff --git a/tests/PHPStan/Analyser/data/bug-13352.php b/tests/bench/data/bug-13352.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-13352.php
rename to tests/bench/data/bug-13352.php
diff --git a/tests/PHPStan/Analyser/data/bug-13685.php b/tests/bench/data/bug-13685.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-13685.php
rename to tests/bench/data/bug-13685.php
diff --git a/tests/PHPStan/Analyser/data/bug-1388.php b/tests/bench/data/bug-1388.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-1388.php
rename to tests/bench/data/bug-1388.php
diff --git a/tests/PHPStan/Analyser/data/bug-13933.php b/tests/bench/data/bug-13933.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-13933.php
rename to tests/bench/data/bug-13933.php
diff --git a/tests/PHPStan/Analyser/data/bug-14207-and.php b/tests/bench/data/bug-14207-and.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-14207-and.php
rename to tests/bench/data/bug-14207-and.php
diff --git a/tests/PHPStan/Analyser/data/bug-14207.php b/tests/bench/data/bug-14207.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-14207.php
rename to tests/bench/data/bug-14207.php
diff --git a/tests/PHPStan/Analyser/data/bug-1447.php b/tests/bench/data/bug-1447.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-1447.php
rename to tests/bench/data/bug-1447.php
diff --git a/tests/PHPStan/Analyser/data/bug-3686.php b/tests/bench/data/bug-3686.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-3686.php
rename to tests/bench/data/bug-3686.php
diff --git a/tests/PHPStan/Analyser/data/bug-4300.php b/tests/bench/data/bug-4300.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-4300.php
rename to tests/bench/data/bug-4300.php
diff --git a/tests/PHPStan/Analyser/data/bug-4308.php b/tests/bench/data/bug-4308.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-4308.php
rename to tests/bench/data/bug-4308.php
diff --git a/tests/PHPStan/Analyser/data/bug-5081.php b/tests/bench/data/bug-5081.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-5081.php
rename to tests/bench/data/bug-5081.php
diff --git a/tests/PHPStan/Analyser/data/bug-5231.php b/tests/bench/data/bug-5231.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-5231.php
rename to tests/bench/data/bug-5231.php
diff --git a/tests/PHPStan/Analyser/data/bug-5231_2.php b/tests/bench/data/bug-5231_2.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-5231_2.php
rename to tests/bench/data/bug-5231_2.php
diff --git a/tests/PHPStan/Analyser/data/bug-5390.php b/tests/bench/data/bug-5390.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-5390.php
rename to tests/bench/data/bug-5390.php
diff --git a/tests/PHPStan/Analyser/data/bug-6265.php b/tests/bench/data/bug-6265.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-6265.php
rename to tests/bench/data/bug-6265.php
diff --git a/tests/PHPStan/Analyser/data/bug-6442.php b/tests/bench/data/bug-6442.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-6442.php
rename to tests/bench/data/bug-6442.php
diff --git a/tests/PHPStan/Analyser/data/bug-6936.php b/tests/bench/data/bug-6936.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-6936.php
rename to tests/bench/data/bug-6936.php
diff --git a/tests/PHPStan/Analyser/data/bug-6948.php b/tests/bench/data/bug-6948.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-6948.php
rename to tests/bench/data/bug-6948.php
diff --git a/tests/PHPStan/Analyser/data/bug-7140.php b/tests/bench/data/bug-7140.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-7140.php
rename to tests/bench/data/bug-7140.php
diff --git a/tests/PHPStan/Analyser/data/bug-7214.php b/tests/bench/data/bug-7214.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-7214.php
rename to tests/bench/data/bug-7214.php
diff --git a/tests/PHPStan/Analyser/data/bug-7581.php b/tests/bench/data/bug-7581.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-7581.php
rename to tests/bench/data/bug-7581.php
diff --git a/tests/PHPStan/Analyser/data/bug-7637.php b/tests/bench/data/bug-7637.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-7637.php
rename to tests/bench/data/bug-7637.php
diff --git a/tests/PHPStan/Analyser/data/bug-7901.php b/tests/bench/data/bug-7901.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-7901.php
rename to tests/bench/data/bug-7901.php
diff --git a/tests/PHPStan/Analyser/data/bug-7903.php b/tests/bench/data/bug-7903.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-7903.php
rename to tests/bench/data/bug-7903.php
diff --git a/tests/PHPStan/Analyser/data/bug-8146a.php b/tests/bench/data/bug-8146a.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-8146a.php
rename to tests/bench/data/bug-8146a.php
diff --git a/tests/PHPStan/Analyser/data/bug-8146b.php b/tests/bench/data/bug-8146b.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-8146b.php
rename to tests/bench/data/bug-8146b.php
diff --git a/tests/PHPStan/Analyser/data/bug-8147.php b/tests/bench/data/bug-8147.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-8147.php
rename to tests/bench/data/bug-8147.php
diff --git a/tests/PHPStan/Analyser/data/bug-8215.php b/tests/bench/data/bug-8215.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-8215.php
rename to tests/bench/data/bug-8215.php
diff --git a/tests/PHPStan/Analyser/data/bug-8503.php b/tests/bench/data/bug-8503.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-8503.php
rename to tests/bench/data/bug-8503.php
diff --git a/tests/PHPStan/Analyser/data/bug-9690.php b/tests/bench/data/bug-9690.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/bug-9690.php
rename to tests/bench/data/bug-9690.php
diff --git a/tests/PHPStan/Analyser/data/conditional-expression-infinite-loop.php b/tests/bench/data/conditional-expression-infinite-loop.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/conditional-expression-infinite-loop.php
rename to tests/bench/data/conditional-expression-infinite-loop.php
diff --git a/tests/PHPStan/Analyser/data/process-called-method-infinite-loop.php b/tests/bench/data/process-called-method-infinite-loop.php
similarity index 100%
rename from tests/PHPStan/Analyser/data/process-called-method-infinite-loop.php
rename to tests/bench/data/process-called-method-infinite-loop.php
diff --git a/tests/bench/storage/baseline.xml b/tests/bench/storage/baseline.xml
new file mode 100644
index 00000000000..e64638ac8cd
--- /dev/null
+++ b/tests/bench/storage/baseline.xml
@@ -0,0 +1,557 @@
+
+
+
+
+
+ Linux
+ runnervm0kj6c
+ 6.14.0-1017-azure
+ #17~24.04.1-Ubuntu SMP Mon Dec 1 20:10:50 UTC 2025
+ x86_64
+
+
+
+ 8.5.3
+ /etc/php/8.5/cli/php.ini
+ Core, date, lexbor, openssl, pcre, zlib, filter, hash, json, uri, Zend OPcache, pcntl, random, Reflection, SPL, session, standard, sodium, libxml, mysqlnd, PDO, xml, apcu, ast, bcmath, bz2, calendar, ctype, curl, dba, dom, enchant, mbstring, FFI, fileinfo, ftp, gd, gettext, gmp, iconv, igbinary, imagick, imap, intl, ldap, exif, memcache, mongodb, msgpack, mysqli, odbc, pdo_dblib, PDO_Firebird, pdo_mysql, PDO_ODBC, pdo_pgsql, pdo_sqlite, pdo_sqlsrv, pgsql, Phar, posix, readline, shmop, SimpleXML, snmp, soap, sockets, sqlite3, sqlsrv, sysvmsg, sysvsem, sysvshm, tidy, tokenizer, xmlreader, xmlwriter, xsl, yaml, zip, zmq, memcached, redis, ds
+
+
+ 1
+
+
+
+ 0.529296875
+ 0.12841796875
+ 0.04296875
+
+
+ git
+ (unnamed branch)
+
+
+
+ 0.0071525573730469
+ 0.16689300537109
+ 1.9149780273438
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/composer.json b/tests/composer.json
index aaad8c1afd1..46b7fefdb4e 100644
--- a/tests/composer.json
+++ b/tests/composer.json
@@ -2,7 +2,8 @@
"name": "phpstan/phpstan-src-tests",
"require-dev": {
"phpunit/phpunit": "^11.5.23",
- "brianium/paratest": "^7.8.3"
+ "brianium/paratest": "^7.8.3",
+ "phpbench/phpbench": "^1.5"
},
"config": {
"platform": {
diff --git a/tests/composer.lock b/tests/composer.lock
index d372ba0a81f..11535d0d88b 100644
--- a/tests/composer.lock
+++ b/tests/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "868be8e811ed8ef2531495ab93a0d835",
+ "content-hash": "806842328c3aeb6bc6f75007f410ebe6",
"packages": [],
"packages-dev": [
{
@@ -100,6 +100,160 @@
],
"time": "2026-01-08T08:02:38+00:00"
},
+ {
+ "name": "doctrine/annotations",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/annotations.git",
+ "reference": "901c2ee5d26eb64ff43c47976e114bf00843acf7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/annotations/zipball/901c2ee5d26eb64ff43c47976e114bf00843acf7",
+ "reference": "901c2ee5d26eb64ff43c47976e114bf00843acf7",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/lexer": "^2 || ^3",
+ "ext-tokenizer": "*",
+ "php": "^7.2 || ^8.0",
+ "psr/cache": "^1 || ^2 || ^3"
+ },
+ "require-dev": {
+ "doctrine/cache": "^2.0",
+ "doctrine/coding-standard": "^10",
+ "phpstan/phpstan": "^1.10.28",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
+ "symfony/cache": "^5.4 || ^6.4 || ^7",
+ "vimeo/psalm": "^4.30 || ^5.14"
+ },
+ "suggest": {
+ "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "Docblock Annotations Parser",
+ "homepage": "https://www.doctrine-project.org/projects/annotations.html",
+ "keywords": [
+ "annotations",
+ "docblock",
+ "parser"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/annotations/issues",
+ "source": "https://github.com/doctrine/annotations/tree/2.0.2"
+ },
+ "abandoned": true,
+ "time": "2024-09-05T10:17:24+00:00"
+ },
+ {
+ "name": "doctrine/lexer",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/lexer.git",
+ "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd",
+ "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^12",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^10.5",
+ "psalm/plugin-phpunit": "^0.18.3",
+ "vimeo/psalm": "^5.21"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Common\\Lexer\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
+ "homepage": "https://www.doctrine-project.org/projects/lexer.html",
+ "keywords": [
+ "annotations",
+ "docblock",
+ "lexer",
+ "parser",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/lexer/issues",
+ "source": "https://github.com/doctrine/lexer/tree/3.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-02-05T11:56:58+00:00"
+ },
{
"name": "fidry/cpu-core-counter",
"version": "1.3.0",
@@ -457,6 +611,156 @@
},
"time": "2022-02-21T01:04:05+00:00"
},
+ {
+ "name": "phpbench/container",
+ "version": "2.2.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpbench/container.git",
+ "reference": "0c7b2d36c1ea53fe27302fb8873ded7172047196"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpbench/container/zipball/0c7b2d36c1ea53fe27302fb8873ded7172047196",
+ "reference": "0c7b2d36c1ea53fe27302fb8873ded7172047196",
+ "shasum": ""
+ },
+ "require": {
+ "psr/container": "^1.0|^2.0",
+ "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "php-cs-fixer/shim": "^3.89",
+ "phpstan/phpstan": "^0.12.52",
+ "phpunit/phpunit": "^8"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PhpBench\\DependencyInjection\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Daniel Leech",
+ "email": "daniel@dantleech.com"
+ }
+ ],
+ "description": "Simple, configurable, service container.",
+ "support": {
+ "issues": "https://github.com/phpbench/container/issues",
+ "source": "https://github.com/phpbench/container/tree/2.2.3"
+ },
+ "time": "2025-11-06T09:05:13+00:00"
+ },
+ {
+ "name": "phpbench/phpbench",
+ "version": "1.5.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpbench/phpbench.git",
+ "reference": "9a28fd0833f11171b949843c6fd663eb69b6d14c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpbench/phpbench/zipball/9a28fd0833f11171b949843c6fd663eb69b6d14c",
+ "reference": "9a28fd0833f11171b949843c6fd663eb69b6d14c",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/annotations": "^2.0",
+ "ext-dom": "*",
+ "ext-json": "*",
+ "ext-pcre": "*",
+ "ext-reflection": "*",
+ "ext-spl": "*",
+ "ext-tokenizer": "*",
+ "php": "^8.2",
+ "phpbench/container": "^2.2",
+ "psr/log": "^1.1 || ^2.0 || ^3.0",
+ "seld/jsonlint": "^1.1",
+ "symfony/console": "^6.1 || ^7.0 || ^8.0",
+ "symfony/filesystem": "^6.1 || ^7.0 || ^8.0",
+ "symfony/finder": "^6.1 || ^7.0 || ^8.0",
+ "symfony/options-resolver": "^6.1 || ^7.0 || ^8.0",
+ "symfony/process": "^6.1 || ^7.0 || ^8.0",
+ "webmozart/glob": "^4.6"
+ },
+ "require-dev": {
+ "dantleech/invoke": "^2.0",
+ "ergebnis/composer-normalize": "^2.39",
+ "jangregor/phpstan-prophecy": "^1.0",
+ "php-cs-fixer/shim": "^3.9",
+ "phpspec/prophecy": "^1.22",
+ "phpstan/extension-installer": "^1.1",
+ "phpstan/phpstan": "^1.0",
+ "phpstan/phpstan-phpunit": "^1.0",
+ "phpunit/phpunit": "^11.5",
+ "rector/rector": "^1.2",
+ "sebastian/exporter": "^6.3.2",
+ "symfony/error-handler": "^6.1 || ^7.0 || ^8.0",
+ "symfony/var-dumper": "^6.1 || ^7.0 || ^8.0"
+ },
+ "suggest": {
+ "ext-xdebug": "For Xdebug profiling extension."
+ },
+ "bin": [
+ "bin/phpbench"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "lib/Report/Func/functions.php"
+ ],
+ "psr-4": {
+ "PhpBench\\": "lib/",
+ "PhpBench\\Extensions\\XDebug\\": "extensions/xdebug/lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Daniel Leech",
+ "email": "daniel@dantleech.com"
+ }
+ ],
+ "description": "PHP Benchmarking Framework",
+ "keywords": [
+ "benchmarking",
+ "optimization",
+ "performance",
+ "profiling",
+ "testing"
+ ],
+ "support": {
+ "issues": "https://github.com/phpbench/phpbench/issues",
+ "source": "https://github.com/phpbench/phpbench/tree/1.5.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/dantleech",
+ "type": "github"
+ }
+ ],
+ "time": "2026-03-05T08:18:58+00:00"
+ },
{
"name": "phpunit/php-code-coverage",
"version": "11.0.12",
@@ -914,6 +1218,55 @@
],
"time": "2026-02-08T07:05:14+00:00"
},
+ {
+ "name": "psr/cache",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/cache.git",
+ "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
+ "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Cache\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for caching libraries",
+ "keywords": [
+ "cache",
+ "psr",
+ "psr-6"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/cache/tree/3.0.0"
+ },
+ "time": "2021-02-03T23:26:27+00:00"
+ },
{
"name": "psr/container",
"version": "2.0.2",
@@ -967,6 +1320,56 @@
},
"time": "2021-11-05T16:47:00+00:00"
},
+ {
+ "name": "psr/log",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+ "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/3.0.2"
+ },
+ "time": "2024-09-11T13:17:53+00:00"
+ },
{
"name": "sebastian/cli-parser",
"version": "3.0.2",
@@ -1953,6 +2356,70 @@
],
"time": "2024-10-09T05:16:32+00:00"
},
+ {
+ "name": "seld/jsonlint",
+ "version": "1.11.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/jsonlint.git",
+ "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/1748aaf847fc731cfad7725aec413ee46f0cc3a2",
+ "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.11",
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13"
+ },
+ "bin": [
+ "bin/jsonlint"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Seld\\JsonLint\\": "src/Seld/JsonLint/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "https://seld.be"
+ }
+ ],
+ "description": "JSON Linter",
+ "keywords": [
+ "json",
+ "linter",
+ "parser",
+ "validator"
+ ],
+ "support": {
+ "issues": "https://github.com/Seldaek/jsonlint/issues",
+ "source": "https://github.com/Seldaek/jsonlint/tree/1.11.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/Seldaek",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-07-11T14:55:45+00:00"
+ },
{
"name": "staabm/side-effects-detector",
"version": "1.0.5",
@@ -2170,6 +2637,215 @@
],
"time": "2024-09-25T14:21:43+00:00"
},
+ {
+ "name": "symfony/filesystem",
+ "version": "v7.4.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/filesystem.git",
+ "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/3ebc794fa5315e59fd122561623c2e2e4280538e",
+ "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-mbstring": "~1.8"
+ },
+ "require-dev": {
+ "symfony/process": "^6.4|^7.0|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Filesystem\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides basic utilities for the filesystem",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/filesystem/tree/v7.4.6"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-02-25T16:50:00+00:00"
+ },
+ {
+ "name": "symfony/finder",
+ "version": "v7.4.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/finder.git",
+ "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/8655bf1076b7a3a346cb11413ffdabff50c7ffcf",
+ "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "symfony/filesystem": "^6.4|^7.0|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Finder\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Finds files and directories via an intuitive fluent interface",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/finder/tree/v7.4.6"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-01-29T09:40:50+00:00"
+ },
+ {
+ "name": "symfony/options-resolver",
+ "version": "v7.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/options-resolver.git",
+ "reference": "b38026df55197f9e39a44f3215788edf83187b80"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/b38026df55197f9e39a44f3215788edf83187b80",
+ "reference": "b38026df55197f9e39a44f3215788edf83187b80",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\OptionsResolver\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides an improved replacement for the array_replace PHP function",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "config",
+ "configuration",
+ "options"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/options-resolver/tree/v7.4.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-11-12T15:39:26+00:00"
+ },
{
"name": "symfony/polyfill-ctype",
"version": "v1.33.0",
@@ -2797,6 +3473,55 @@
}
],
"time": "2025-11-17T20:03:58+00:00"
+ },
+ {
+ "name": "webmozart/glob",
+ "version": "4.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/webmozarts/glob.git",
+ "reference": "8a2842112d6916e61e0e15e316465b611f3abc17"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/webmozarts/glob/zipball/8a2842112d6916e61e0e15e316465b611f3abc17",
+ "reference": "8a2842112d6916e61e0e15e316465b611f3abc17",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.3 || ^8.0.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.5",
+ "symfony/filesystem": "^5.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Webmozart\\Glob\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ }
+ ],
+ "description": "A PHP implementation of Ant's glob.",
+ "support": {
+ "issues": "https://github.com/webmozarts/glob/issues",
+ "source": "https://github.com/webmozarts/glob/tree/4.7.0"
+ },
+ "time": "2024-03-07T20:33:40+00:00"
}
],
"aliases": [],