From d4a5909e1f703b846677816ce3c80ee9f59c98fb Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Thu, 1 Feb 2024 08:10:57 +0100 Subject: [PATCH 1/9] Fix additional places where base_dir was broken due to missing separator Improves upon https://github.com/vimeo/psalm/pull/10542 and https://github.com/vimeo/psalm/pull/10628 --- src/Psalm/Config.php | 12 ++++++------ tests/Cache/CacheTest.php | 34 +++++++++++++++++----------------- tests/StubTest.php | 2 +- tests/TestConfig.php | 4 +--- 4 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/Psalm/Config.php b/src/Psalm/Config.php index e6f05540b55..bebf471599c 100644 --- a/src/Psalm/Config.php +++ b/src/Psalm/Config.php @@ -244,7 +244,7 @@ class Config protected $extra_files; /** - * The base directory of this config file + * The base directory of this config file without trailing slash * * @var string */ @@ -1445,7 +1445,7 @@ private static function fromXmlAndPaths( if (!$file_path) { throw new ConfigException( 'Cannot resolve stubfile path ' - . rtrim($config->base_dir, DIRECTORY_SEPARATOR) + . $config->base_dir . DIRECTORY_SEPARATOR . $stub_file['name'], ); @@ -1582,11 +1582,11 @@ public function safeSetCustomErrorLevel(string $issue_key, string $error_level): private function loadFileExtensions(SimpleXMLElement $extensions): void { foreach ($extensions as $extension) { - $extension_name = preg_replace('/^\.?/', '', (string)$extension['name'], 1); + $extension_name = preg_replace('/^\.?/', '', (string) $extension['name'], 1); $this->file_extensions[] = $extension_name; if (isset($extension['scanner'])) { - $path = $this->base_dir . (string)$extension['scanner']; + $path = $this->base_dir . DIRECTORY_SEPARATOR . (string) $extension['scanner']; if (!file_exists($path)) { throw new ConfigException('Error parsing config: cannot find file ' . $path); @@ -1596,7 +1596,7 @@ private function loadFileExtensions(SimpleXMLElement $extensions): void } if (isset($extension['checker'])) { - $path = $this->base_dir . (string)$extension['checker']; + $path = $this->base_dir . DIRECTORY_SEPARATOR . (string) $extension['checker']; if (!file_exists($path)) { throw new ConfigException('Error parsing config: cannot find file ' . $path); @@ -1817,7 +1817,7 @@ private function getPluginClassForPath(Codebase $codebase, string $path, string public function shortenFileName(string $to): string { if (!is_file($to)) { - return preg_replace('/^' . preg_quote($this->base_dir, '/') . '/', '', $to, 1); + return preg_replace('/^' . preg_quote($this->base_dir . DIRECTORY_SEPARATOR, '/') . '?/', '', $to, 1); } $from = $this->base_dir; diff --git a/tests/Cache/CacheTest.php b/tests/Cache/CacheTest.php index e714256837a..c696aef96dd 100644 --- a/tests/Cache/CacheTest.php +++ b/tests/Cache/CacheTest.php @@ -92,7 +92,7 @@ public function testCacheInteractions( foreach ($interactions as $interaction) { foreach ($interaction['files'] as $file_path => $file_contents) { - $file_path = $config->base_dir . str_replace('/', DIRECTORY_SEPARATOR, $file_path); + $file_path = $config->base_dir . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $file_path); if ($file_contents === null) { $file_provider->deleteFile($file_path); } else { @@ -126,7 +126,7 @@ public static function provideCacheInteractions(): iterable [ [ 'files' => [ - '/src/A.php' => <<<'PHP' + 'src/A.php' => <<<'PHP' <<<'PHP' + 'src/B.php' => <<<'PHP' [ - '/src/B.php' => null, + 'src/B.php' => null, ], 'issues' => [ - '/src/A.php' => [ + 'src/A.php' => [ 'UndefinedClass: Class, interface or enum named B does not exist', ], ], @@ -163,7 +163,7 @@ public function do(): void [ [ 'files' => [ - '/src/A.php' => <<<'PHP' + 'src/A.php' => <<<'PHP' <<<'PHP' + 'src/B.php' => <<<'PHP' [ - '/src/A.php' => [ + 'src/A.php' => [ "NullableReturnStatement: The declared return type 'int' for A::foo is not nullable, but the function returns 'int|null'", "InvalidNullableReturnType: The declared return type 'int' for A::foo is not nullable, but 'int|null' contains null", ], @@ -188,7 +188,7 @@ class B { ], [ 'files' => [ - '/src/B.php' => <<<'PHP' + 'src/B.php' => <<<'PHP' [ - '/src/A.php' => <<<'PHP' + 'src/A.php' => <<<'PHP' <<<'PHP' + 'src/B.php' => <<<'PHP' [ - '/src/A.php' => <<<'PHP' + 'src/A.php' => <<<'PHP' [ - '/src/A.php' => [ + 'src/A.php' => [ "UndefinedDocblockClass: Docblock-defined class, interface or enum named T does not exist", ], - '/src/B.php' => [ + 'src/B.php' => [ "InvalidArgument: Argument 1 of A::foo expects T, but 1 provided", ], ], @@ -266,7 +266,7 @@ public function foo($baz): void [ [ 'files' => [ - '/src/A.php' => <<<'PHP' + 'src/A.php' => <<<'PHP' [ - '/src/A.php' => <<<'PHP' + 'src/A.php' => <<<'PHP' [ - '/src/A.php' => [ + 'src/A.php' => [ "UndefinedThisPropertyFetch: Instance property A::\$foo is not defined", "MixedReturnStatement: Could not infer a return type", "MixedInferredReturnType: Could not verify return type 'string' for A::bar", diff --git a/tests/StubTest.php b/tests/StubTest.php index f12fb943ed8..1e297daf976 100644 --- a/tests/StubTest.php +++ b/tests/StubTest.php @@ -864,7 +864,7 @@ function_exists("fooBar"); public function testNoStubFunction(): void { - $this->expectExceptionMessage('UndefinedFunction - /src/somefile.php:2:22 - Function barBar does not exist'); + $this->expectExceptionMessage('UndefinedFunction'); $this->expectException(CodeException::class); $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( diff --git a/tests/TestConfig.php b/tests/TestConfig.php index dc72087410f..1b8a1ea5c94 100644 --- a/tests/TestConfig.php +++ b/tests/TestConfig.php @@ -9,8 +9,6 @@ use function getcwd; -use const DIRECTORY_SEPARATOR; - class TestConfig extends Config { private static ?ProjectFileFilter $cached_project_files = null; @@ -28,7 +26,7 @@ public function __construct() $this->level = 1; $this->cache_directory = null; - $this->base_dir = getcwd() . DIRECTORY_SEPARATOR; + $this->base_dir = getcwd(); if (!self::$cached_project_files) { self::$cached_project_files = ProjectFileFilter::loadFromXMLElement( From f185f3d98593233d9b68b05959bc10adb6c5876a Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Thu, 1 Feb 2024 08:46:18 +0100 Subject: [PATCH 2/9] additional places with inconsistent trailing slash --- src/Psalm/Internal/Cli/LanguageServer.php | 6 +++--- src/Psalm/Internal/Cli/Plugin.php | 6 ++---- src/Psalm/Internal/Cli/Psalm.php | 12 ++++++------ src/Psalm/Internal/Cli/Psalter.php | 6 +++--- src/Psalm/Internal/Cli/Refactor.php | 6 +++--- .../PluginManager/Command/DisableCommand.php | 4 +--- .../Internal/PluginManager/Command/EnableCommand.php | 4 +--- .../Internal/PluginManager/Command/ShowCommand.php | 4 +--- .../Internal/PluginManager/PluginListFactory.php | 10 ++++------ 9 files changed, 24 insertions(+), 34 deletions(-) diff --git a/src/Psalm/Internal/Cli/LanguageServer.php b/src/Psalm/Internal/Cli/LanguageServer.php index 1dc16fbe5bf..0fa174eff1f 100644 --- a/src/Psalm/Internal/Cli/LanguageServer.php +++ b/src/Psalm/Internal/Cli/LanguageServer.php @@ -258,12 +258,12 @@ static function (string $arg) use ($valid_long_options): void { $options['r'] = $options['root']; } - $current_dir = (string)getcwd() . DIRECTORY_SEPARATOR; + $current_dir = (string) getcwd(); if (isset($options['r']) && is_string($options['r'])) { $root_path = realpath($options['r']); - if (!$root_path) { + if ($root_path === false) { fwrite( STDERR, 'Could not locate root directory ' . $current_dir . DIRECTORY_SEPARATOR . $options['r'] . PHP_EOL, @@ -271,7 +271,7 @@ static function (string $arg) use ($valid_long_options): void { exit(1); } - $current_dir = $root_path . DIRECTORY_SEPARATOR; + $current_dir = $root_path; } $vendor_dir = CliUtils::getVendorDir($current_dir); diff --git a/src/Psalm/Internal/Cli/Plugin.php b/src/Psalm/Internal/Cli/Plugin.php index 2388238262d..c89cbeed54c 100644 --- a/src/Psalm/Internal/Cli/Plugin.php +++ b/src/Psalm/Internal/Cli/Plugin.php @@ -12,8 +12,6 @@ use function dirname; use function getcwd; -use const DIRECTORY_SEPARATOR; - // phpcs:disable PSR1.Files.SideEffects require_once __DIR__ . '/../CliUtils.php'; @@ -27,13 +25,13 @@ final class Plugin public static function run(): void { CliUtils::checkRuntimeRequirements(); - $current_dir = (string)getcwd() . DIRECTORY_SEPARATOR; + $current_dir = (string) getcwd(); $vendor_dir = CliUtils::getVendorDir($current_dir); CliUtils::requireAutoloaders($current_dir, false, $vendor_dir); $app = new Application('psalm-plugin', PSALM_VERSION); - $psalm_root = dirname(__DIR__, 4) . DIRECTORY_SEPARATOR; + $psalm_root = dirname(__DIR__, 4); $plugin_list_factory = new PluginListFactory($current_dir, $psalm_root); diff --git a/src/Psalm/Internal/Cli/Psalm.php b/src/Psalm/Internal/Cli/Psalm.php index c354cf21a58..c8a5a4ee20c 100644 --- a/src/Psalm/Internal/Cli/Psalm.php +++ b/src/Psalm/Internal/Cli/Psalm.php @@ -485,7 +485,7 @@ static function (string $arg): void { */ private static function generateConfig(string $current_dir, array &$args): void { - if (file_exists($current_dir . 'psalm.xml')) { + if (file_exists($current_dir . DIRECTORY_SEPARATOR . 'psalm.xml')) { die('A config file already exists in the current directory' . PHP_EOL); } @@ -535,7 +535,7 @@ private static function generateConfig(string $current_dir, array &$args): void die($e->getMessage() . PHP_EOL); } - if (!file_put_contents($current_dir . 'psalm.xml', $template_contents)) { + if (!file_put_contents($current_dir . DIRECTORY_SEPARATOR . 'psalm.xml', $template_contents)) { die('Could not write to psalm.xml' . PHP_EOL); } @@ -779,7 +779,7 @@ private static function autoGenerateConfig( die($e->getMessage() . PHP_EOL); } - if (!file_put_contents($current_dir . 'psalm.xml', $template_contents)) { + if (!file_put_contents($current_dir . DIRECTORY_SEPARATOR . 'psalm.xml', $template_contents)) { die('Could not write to psalm.xml' . PHP_EOL); } @@ -840,12 +840,12 @@ private static function getCurrentDir(array $options): string exit(1); } - $current_dir = $cwd . DIRECTORY_SEPARATOR; + $current_dir = $cwd; if (isset($options['r']) && is_string($options['r'])) { $root_path = realpath($options['r']); - if (!$root_path) { + if ($root_path === false) { fwrite( STDERR, 'Could not locate root directory ' . $current_dir . DIRECTORY_SEPARATOR . $options['r'] . PHP_EOL, @@ -853,7 +853,7 @@ private static function getCurrentDir(array $options): string exit(1); } - $current_dir = $root_path . DIRECTORY_SEPARATOR; + $current_dir = $root_path; } return $current_dir; diff --git a/src/Psalm/Internal/Cli/Psalter.php b/src/Psalm/Internal/Cli/Psalter.php index 9dd8eaf47d0..5b53ec0dc13 100644 --- a/src/Psalm/Internal/Cli/Psalter.php +++ b/src/Psalm/Internal/Cli/Psalter.php @@ -194,16 +194,16 @@ public static function run(array $argv): void exit(1); } - $current_dir = (string)getcwd() . DIRECTORY_SEPARATOR; + $current_dir = (string) getcwd(); if (isset($options['r']) && is_string($options['r'])) { $root_path = realpath($options['r']); - if (!$root_path) { + if ($root_path === false) { die('Could not locate root directory ' . $current_dir . DIRECTORY_SEPARATOR . $options['r'] . PHP_EOL); } - $current_dir = $root_path . DIRECTORY_SEPARATOR; + $current_dir = $root_path; } $vendor_dir = CliUtils::getVendorDir($current_dir); diff --git a/src/Psalm/Internal/Cli/Refactor.php b/src/Psalm/Internal/Cli/Refactor.php index 0fca3ab46f2..22761b873f1 100644 --- a/src/Psalm/Internal/Cli/Refactor.php +++ b/src/Psalm/Internal/Cli/Refactor.php @@ -165,16 +165,16 @@ static function (string $arg) use ($valid_long_options): void { $options['r'] = $options['root']; } - $current_dir = (string)getcwd() . DIRECTORY_SEPARATOR; + $current_dir = (string) getcwd(); if (isset($options['r']) && is_string($options['r'])) { $root_path = realpath($options['r']); - if (!$root_path) { + if ($root_path === false) { die('Could not locate root directory ' . $current_dir . DIRECTORY_SEPARATOR . $options['r'] . PHP_EOL); } - $current_dir = $root_path . DIRECTORY_SEPARATOR; + $current_dir = $root_path; } $vendor_dir = CliUtils::getVendorDir($current_dir); diff --git a/src/Psalm/Internal/PluginManager/Command/DisableCommand.php b/src/Psalm/Internal/PluginManager/Command/DisableCommand.php index af7b4bb90d9..7c1e6b9a27a 100644 --- a/src/Psalm/Internal/PluginManager/Command/DisableCommand.php +++ b/src/Psalm/Internal/PluginManager/Command/DisableCommand.php @@ -16,8 +16,6 @@ use function getcwd; use function is_string; -use const DIRECTORY_SEPARATOR; - /** * @internal */ @@ -50,7 +48,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); - $current_dir = (string) getcwd() . DIRECTORY_SEPARATOR; + $current_dir = (string) getcwd(); $config_file_path = $input->getOption('config'); if ($config_file_path !== null && !is_string($config_file_path)) { diff --git a/src/Psalm/Internal/PluginManager/Command/EnableCommand.php b/src/Psalm/Internal/PluginManager/Command/EnableCommand.php index 6278b7018f2..0a8df8d1dfe 100644 --- a/src/Psalm/Internal/PluginManager/Command/EnableCommand.php +++ b/src/Psalm/Internal/PluginManager/Command/EnableCommand.php @@ -16,8 +16,6 @@ use function getcwd; use function is_string; -use const DIRECTORY_SEPARATOR; - /** * @internal */ @@ -50,7 +48,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); - $current_dir = (string) getcwd() . DIRECTORY_SEPARATOR; + $current_dir = (string) getcwd(); $config_file_path = $input->getOption('config'); if ($config_file_path !== null && !is_string($config_file_path)) { diff --git a/src/Psalm/Internal/PluginManager/Command/ShowCommand.php b/src/Psalm/Internal/PluginManager/Command/ShowCommand.php index a8e78a732c4..ecc24712ce4 100644 --- a/src/Psalm/Internal/PluginManager/Command/ShowCommand.php +++ b/src/Psalm/Internal/PluginManager/Command/ShowCommand.php @@ -17,8 +17,6 @@ use function getcwd; use function is_string; -use const DIRECTORY_SEPARATOR; - /** * @internal */ @@ -44,7 +42,7 @@ protected function configure(): void protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); - $current_dir = (string) getcwd() . DIRECTORY_SEPARATOR; + $current_dir = (string) getcwd(); $config_file_path = $input->getOption('config'); if ($config_file_path !== null && !is_string($config_file_path)) { diff --git a/src/Psalm/Internal/PluginManager/PluginListFactory.php b/src/Psalm/Internal/PluginManager/PluginListFactory.php index 950b6dd24a6..927d0f8c32e 100644 --- a/src/Psalm/Internal/PluginManager/PluginListFactory.php +++ b/src/Psalm/Internal/PluginManager/PluginListFactory.php @@ -7,10 +7,8 @@ use function array_filter; use function json_encode; -use function rtrim; use function urlencode; -use const DIRECTORY_SEPARATOR; use const JSON_THROW_ON_ERROR; /** @@ -53,13 +51,13 @@ private function findLockFiles(): array if ($this->psalm_root === $this->project_root) { // managing plugins for psalm itself $composer_lock_filenames = [ - Composer::getLockFilePath(rtrim($this->psalm_root, DIRECTORY_SEPARATOR)), + Composer::getLockFilePath($this->psalm_root), ]; } else { $composer_lock_filenames = [ - Composer::getLockFilePath(rtrim($this->project_root, DIRECTORY_SEPARATOR)), - Composer::getLockFilePath(rtrim($this->psalm_root, DIRECTORY_SEPARATOR) . '/../../..'), - Composer::getLockFilePath(rtrim($this->psalm_root, DIRECTORY_SEPARATOR)), + Composer::getLockFilePath($this->project_root), + Composer::getLockFilePath($this->psalm_root . '/../../..'), + Composer::getLockFilePath($this->psalm_root), ]; } From 47c52ad60225877fa92f394a7f4d9213974ad12f Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Thu, 1 Feb 2024 12:28:32 +0100 Subject: [PATCH 3/9] fix /src/psalm.xml not removed between tests and remove psalm.xml at the end of tests --- tests/EndToEnd/PsalmEndToEndTest.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/EndToEnd/PsalmEndToEndTest.php b/tests/EndToEnd/PsalmEndToEndTest.php index b02660cecd2..bdbb2cb1a0e 100644 --- a/tests/EndToEnd/PsalmEndToEndTest.php +++ b/tests/EndToEnd/PsalmEndToEndTest.php @@ -24,6 +24,8 @@ use function tempnam; use function unlink; +use const DIRECTORY_SEPARATOR; + /** * Tests some of the most important use cases of the psalm and psalter commands, by launching a new * process as if invoked by a real user. @@ -47,8 +49,6 @@ public static function setUpBeforeClass(): void throw new Exception('Couldn\'t get working directory'); } - mkdir(self::$tmpDir . '/src'); - copy(__DIR__ . '/../fixtures/DummyProjectWithErrors/composer.json', self::$tmpDir . '/composer.json'); $process = new Process(['composer', 'install', '--no-plugins'], self::$tmpDir, null, null, 120); @@ -63,7 +63,8 @@ public static function tearDownAfterClass(): void public function setUp(): void { - @unlink(self::$tmpDir . '/psalm.xml'); + mkdir(self::$tmpDir . '/src'); + copy( __DIR__ . '/../fixtures/DummyProjectWithErrors/src/FileWithErrors.php', self::$tmpDir . '/src/FileWithErrors.php', @@ -73,9 +74,16 @@ public function setUp(): void public function tearDown(): void { + @unlink(self::$tmpDir . '/psalm.xml'); + if (file_exists(self::$tmpDir . '/cache')) { self::recursiveRemoveDirectory(self::$tmpDir . '/cache'); } + + if (file_exists(self::$tmpDir . '/src')) { + self::recursiveRemoveDirectory(self::$tmpDir . '/src'); + } + parent::tearDown(); } @@ -275,7 +283,7 @@ private static function recursiveRemoveDirectory(string $src): void $dir = opendir($src); while (false !== ($file = readdir($dir))) { if (($file !== '.') && ($file !== '..')) { - $full = $src . '/' . $file; + $full = $src . DIRECTORY_SEPARATOR . $file; if (is_dir($full)) { self::recursiveRemoveDirectory($full); } else { From fae1d414fdedd55defbd507a9cb2d5841ceab887 Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Thu, 1 Feb 2024 18:10:40 +0100 Subject: [PATCH 4/9] fix errors output in stdout making test fails with cryptic errors --- src/Psalm/Internal/Cli/Psalm.php | 31 +++++++++++++++-------- src/Psalm/Internal/Cli/Psalter.php | 39 +++++++++++++++++++++-------- src/Psalm/Internal/Cli/Refactor.php | 24 ++++++++++++------ src/Psalm/Internal/CliUtils.php | 3 ++- 4 files changed, 68 insertions(+), 29 deletions(-) diff --git a/src/Psalm/Internal/Cli/Psalm.php b/src/Psalm/Internal/Cli/Psalm.php index c8a5a4ee20c..5aacced0f61 100644 --- a/src/Psalm/Internal/Cli/Psalm.php +++ b/src/Psalm/Internal/Cli/Psalm.php @@ -276,7 +276,8 @@ public static function run(array $argv): void if (isset($options['set-baseline'])) { if (is_array($options['set-baseline'])) { - die('Only one baseline file can be created at a time' . PHP_EOL); + fwrite(STDERR, 'Only one baseline file can be created at a time' . PHP_EOL); + exit(1); } } @@ -486,7 +487,8 @@ static function (string $arg): void { private static function generateConfig(string $current_dir, array &$args): void { if (file_exists($current_dir . DIRECTORY_SEPARATOR . 'psalm.xml')) { - die('A config file already exists in the current directory' . PHP_EOL); + fwrite(STDERR, 'A config file already exists in the current directory' . PHP_EOL); + exit(1); } $args = array_values(array_filter( @@ -507,12 +509,14 @@ private static function generateConfig(string $current_dir, array &$args): void $init_source_dir = null; if (count($args)) { if (count($args) > 2) { - die('Too many arguments provided for psalm --init' . PHP_EOL); + fwrite(STDERR, 'Too many arguments provided for psalm --init' . PHP_EOL); + exit(1); } if (isset($args[1])) { if (!preg_match('/^[1-8]$/', $args[1])) { - die('Config strictness must be a number between 1 and 8 inclusive' . PHP_EOL); + fwrite(STDERR, 'Config strictness must be a number between 1 and 8 inclusive' . PHP_EOL); + exit(1); } $init_level = (int)$args[1]; @@ -532,11 +536,13 @@ private static function generateConfig(string $current_dir, array &$args): void $vendor_dir, ); } catch (ConfigCreationException $e) { - die($e->getMessage() . PHP_EOL); + fwrite(STDERR, $e->getMessage() . PHP_EOL); + exit(1); } - if (!file_put_contents($current_dir . DIRECTORY_SEPARATOR . 'psalm.xml', $template_contents)) { - die('Could not write to psalm.xml' . PHP_EOL); + if (file_put_contents($current_dir . DIRECTORY_SEPARATOR . 'psalm.xml', $template_contents) === false) { + fwrite(STDERR, 'Could not write to psalm.xml' . PHP_EOL); + exit(1); } exit('Config file created successfully. Please re-run psalm.' . PHP_EOL); @@ -681,7 +687,8 @@ private static function updateBaseline(array $options, Config $config): array $baselineFile = $config->error_baseline; if (empty($baselineFile)) { - die('Cannot update baseline, because no baseline file is configured.' . PHP_EOL); + fwrite(STDERR, 'Cannot update baseline, because no baseline file is configured.' . PHP_EOL); + exit(1); } try { @@ -776,11 +783,13 @@ private static function autoGenerateConfig( $vendor_dir, ); } catch (ConfigCreationException $e) { - die($e->getMessage() . PHP_EOL); + fwrite(STDERR, $e->getMessage() . PHP_EOL); + exit(1); } - if (!file_put_contents($current_dir . DIRECTORY_SEPARATOR . 'psalm.xml', $template_contents)) { - die('Could not write to psalm.xml' . PHP_EOL); + if (file_put_contents($current_dir . DIRECTORY_SEPARATOR . 'psalm.xml', $template_contents) === false) { + fwrite(STDERR, 'Could not write to psalm.xml' . PHP_EOL); + exit(1); } exit('Config file created successfully. Please re-run psalm.' . PHP_EOL); diff --git a/src/Psalm/Internal/Cli/Psalter.php b/src/Psalm/Internal/Cli/Psalter.php index 5b53ec0dc13..d42a1f10843 100644 --- a/src/Psalm/Internal/Cli/Psalter.php +++ b/src/Psalm/Internal/Cli/Psalter.php @@ -112,7 +112,8 @@ public static function run(array $argv): void self::syncShortOptions($options); if (isset($options['c']) && is_array($options['c'])) { - die('Too many config files provided' . PHP_EOL); + fwrite(STDERR, 'Too many config files provided' . PHP_EOL); + exit(1); } if (array_key_exists('h', $options)) { @@ -200,7 +201,11 @@ public static function run(array $argv): void $root_path = realpath($options['r']); if ($root_path === false) { - die('Could not locate root directory ' . $current_dir . DIRECTORY_SEPARATOR . $options['r'] . PHP_EOL); + fwrite( + STDERR, + 'Could not locate root directory ' . $current_dir . DIRECTORY_SEPARATOR . $options['r'] . PHP_EOL, + ); + exit(1); } $current_dir = $root_path; @@ -304,7 +309,8 @@ public static function run(array $argv): void if (array_key_exists('issues', $options)) { if (!is_string($options['issues']) || !$options['issues']) { - die('Expecting a comma-separated list of issues' . PHP_EOL); + fwrite(STDERR, 'Expecting a comma-separated list of issues' . PHP_EOL); + exit(1); } $issues = explode(',', $options['issues']); @@ -339,7 +345,11 @@ public static function run(array $argv): void ); if ($allow_backwards_incompatible_changes === null) { - die('--allow-backwards-incompatible-changes expects a boolean value [true|false|1|0]' . PHP_EOL); + fwrite( + STDERR, + '--allow-backwards-incompatible-changes expects a boolean value [true|false|1|0]' . PHP_EOL, + ); + exit(1); } $project_analyzer->getCodebase()->allow_backwards_incompatible_changes @@ -354,7 +364,11 @@ public static function run(array $argv): void ); if ($doc_block_add_new_line_before_return === null) { - die('--add-newline-between-docblock-annotations expects a boolean value [true|false|1|0]' . PHP_EOL); + fwrite( + STDERR, + '--add-newline-between-docblock-annotations expects a boolean value [true|false|1|0]' . PHP_EOL, + ); + exit(1); } ParsedDocblock::addNewLineBetweenAnnotations($doc_block_add_new_line_before_return); @@ -505,7 +519,8 @@ private static function loadCodeowners(Providers $providers): array } elseif (file_exists('docs/CODEOWNERS')) { $codeowners_file_path = realpath('docs/CODEOWNERS'); } else { - die('Cannot use --codeowner without a CODEOWNERS file' . PHP_EOL); + fwrite(STDERR, 'Cannot use --codeowner without a CODEOWNERS file' . PHP_EOL); + exit(1); } $codeowners_file = file_get_contents($codeowners_file_path); @@ -555,7 +570,8 @@ static function (string $line): bool { } if (!$codeowner_files) { - die('Could not find any available entries in CODEOWNERS' . PHP_EOL); + fwrite(STDERR, 'Could not find any available entries in CODEOWNERS' . PHP_EOL); + exit(1); } return $codeowner_files; @@ -571,11 +587,13 @@ private static function loadCodeownersFiles(array $desired_codeowners, array $co /** @psalm-suppress MixedAssignment */ foreach ($desired_codeowners as $desired_codeowner) { if (!is_string($desired_codeowner)) { - die('Invalid --codeowner ' . (string)$desired_codeowner . PHP_EOL); + fwrite(STDERR, 'Invalid --codeowner ' . (string) $desired_codeowner . PHP_EOL); + exit(1); } if ($desired_codeowner[0] !== '@') { - die('--codeowner option must start with @' . PHP_EOL); + fwrite(STDERR, '--codeowner option must start with @' . PHP_EOL); + exit(1); } $matched_file = false; @@ -588,7 +606,8 @@ private static function loadCodeownersFiles(array $desired_codeowners, array $co } if (!$matched_file) { - die('User/group ' . $desired_codeowner . ' does not own any PHP files' . PHP_EOL); + fwrite(STDERR, 'User/group ' . $desired_codeowner . ' does not own any PHP files' . PHP_EOL); + exit(1); } } diff --git a/src/Psalm/Internal/Cli/Refactor.php b/src/Psalm/Internal/Cli/Refactor.php index 22761b873f1..b23bcb863c2 100644 --- a/src/Psalm/Internal/Cli/Refactor.php +++ b/src/Psalm/Internal/Cli/Refactor.php @@ -121,7 +121,8 @@ static function (string $arg) use ($valid_long_options): void { } if (isset($options['c']) && is_array($options['c'])) { - die('Too many config files provided' . PHP_EOL); + fwrite(STDERR, 'Too many config files provided' . PHP_EOL); + exit(1); } if (array_key_exists('h', $options)) { @@ -171,7 +172,11 @@ static function (string $arg) use ($valid_long_options): void { $root_path = realpath($options['r']); if ($root_path === false) { - die('Could not locate root directory ' . $current_dir . DIRECTORY_SEPARATOR . $options['r'] . PHP_EOL); + fwrite( + STDERR, + 'Could not locate root directory ' . $current_dir . DIRECTORY_SEPARATOR . $options['r'] . PHP_EOL, + ); + exit(1); } $current_dir = $root_path; @@ -210,7 +215,8 @@ static function (string $arg) use ($valid_long_options): void { if ($arg === '--into') { if ($operation !== 'move' || !$last_arg) { - die('--into is not expected here' . PHP_EOL); + fwrite(STDERR, '--into is not expected here' . PHP_EOL); + exit(1); } $operation = 'move_into'; @@ -224,7 +230,8 @@ static function (string $arg) use ($valid_long_options): void { if ($arg === '--to') { if ($operation !== 'rename' || !$last_arg) { - die('--to is not expected here' . PHP_EOL); + fwrite(STDERR, '--to is not expected here' . PHP_EOL); + exit(1); } $operation = 'rename_to'; @@ -239,7 +246,8 @@ static function (string $arg) use ($valid_long_options): void { if ($operation === 'move_into' || $operation === 'rename_to') { if (!$last_arg) { - die('Expecting a previous argument' . PHP_EOL); + fwrite(STDERR, 'Expecting a previous argument' . PHP_EOL); + exit(1); } if ($operation === 'move_into') { @@ -273,11 +281,13 @@ static function (string $arg) use ($valid_long_options): void { continue; } - die('Unexpected argument "' . $arg . '"' . PHP_EOL); + fwrite(STDERR, 'Unexpected argument "' . $arg . '"' . PHP_EOL); + exit(1); } if (!$to_refactor) { - die('No --move or --rename arguments supplied' . PHP_EOL); + fwrite(STDERR, 'No --move or --rename arguments supplied' . PHP_EOL); + exit(1); } $config = CliUtils::initializeConfig( diff --git a/src/Psalm/Internal/CliUtils.php b/src/Psalm/Internal/CliUtils.php index e90f73e4e5d..8f0f1fbf9cb 100644 --- a/src/Psalm/Internal/CliUtils.php +++ b/src/Psalm/Internal/CliUtils.php @@ -483,7 +483,8 @@ public static function initPhpVersion(array $options, Config $config, ProjectAna if (isset($options['php-version'])) { if (!is_string($options['php-version'])) { - die('Expecting a version number in the format x.y' . PHP_EOL); + fwrite(STDERR, 'Expecting a version number in the format x.y' . PHP_EOL); + exit(1); } $version = $options['php-version']; $source = 'cli'; From d79f77215b51df8238a06c26d08759df2a673edb Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Thu, 1 Feb 2024 08:47:24 +0100 Subject: [PATCH 5/9] improve getcwd return type --- dictionaries/CallMap.php | 2 +- dictionaries/CallMap_historical.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dictionaries/CallMap.php b/dictionaries/CallMap.php index cec0545f126..130468e475f 100644 --- a/dictionaries/CallMap.php +++ b/dictionaries/CallMap.php @@ -3296,7 +3296,7 @@ 'get_resource_type' => ['string', 'resource'=>'resource'], 'get_resources' => ['array', 'type='=>'?string'], 'getallheaders' => ['array|false'], -'getcwd' => ['string|false'], +'getcwd' => ['non-falsy-string|false'], 'getdate' => ['array{seconds: int<0, 59>, minutes: int<0, 59>, hours: int<0, 23>, mday: int<1, 31>, wday: int<0, 6>, mon: int<1, 12>, year: int, yday: int<0, 365>, weekday: "Monday"|"Tuesday"|"Wednesday"|"Thursday"|"Friday"|"Saturday"|"Sunday", month: "January"|"February"|"March"|"April"|"May"|"June"|"July"|"August"|"September"|"October"|"November"|"December", 0: int}', 'timestamp='=>'?int'], 'getenv' => ['string|false', 'name'=>'string', 'local_only='=>'bool'], 'getenv\'1' => ['array'], diff --git a/dictionaries/CallMap_historical.php b/dictionaries/CallMap_historical.php index 61e3db09d55..889e1b4fb12 100644 --- a/dictionaries/CallMap_historical.php +++ b/dictionaries/CallMap_historical.php @@ -10661,7 +10661,7 @@ 'get_resource_type' => ['string', 'resource'=>'resource'], 'get_resources' => ['array', 'type='=>'string'], 'getallheaders' => ['array|false'], - 'getcwd' => ['string|false'], + 'getcwd' => ['non-falsy-string|false'], 'getdate' => ['array{seconds: int<0, 59>, minutes: int<0, 59>, hours: int<0, 23>, mday: int<1, 31>, wday: int<0, 6>, mon: int<1, 12>, year: int, yday: int<0, 365>, weekday: "Monday"|"Tuesday"|"Wednesday"|"Thursday"|"Friday"|"Saturday"|"Sunday", month: "January"|"February"|"March"|"April"|"May"|"June"|"July"|"August"|"September"|"October"|"November"|"December", 0: int}', 'timestamp='=>'int'], 'getenv' => ['string|false', 'name'=>'string', 'local_only='=>'bool'], 'gethostbyaddr' => ['string|false', 'ip'=>'string'], From d2e5a0722b75eba39de9e5b78032eb6e33aa6797 Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Thu, 1 Feb 2024 09:08:22 +0100 Subject: [PATCH 6/9] improve realpath and readlink return type --- dictionaries/CallMap.php | 22 +++++++++++----------- dictionaries/CallMap_historical.php | 22 +++++++++++----------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/dictionaries/CallMap.php b/dictionaries/CallMap.php index 130468e475f..048c7287da7 100644 --- a/dictionaries/CallMap.php +++ b/dictionaries/CallMap.php @@ -1590,7 +1590,7 @@ 'DirectoryIterator::getPathInfo' => ['?SplFileInfo', 'class='=>'?class-string'], 'DirectoryIterator::getPathname' => ['string'], 'DirectoryIterator::getPerms' => ['int'], -'DirectoryIterator::getRealPath' => ['string'], +'DirectoryIterator::getRealPath' => ['non-falsy-string'], 'DirectoryIterator::getSize' => ['int'], 'DirectoryIterator::getType' => ['string'], 'DirectoryIterator::isDir' => ['bool'], @@ -2827,7 +2827,7 @@ 'FilesystemIterator::getPathInfo' => ['?SplFileInfo', 'class='=>'?class-string'], 'FilesystemIterator::getPathname' => ['string'], 'FilesystemIterator::getPerms' => ['int'], -'FilesystemIterator::getRealPath' => ['string'], +'FilesystemIterator::getRealPath' => ['non-falsy-string'], 'FilesystemIterator::getSize' => ['int'], 'FilesystemIterator::getType' => ['string'], 'FilesystemIterator::isDir' => ['bool'], @@ -3343,7 +3343,7 @@ 'GlobIterator::getPathInfo' => ['?SplFileInfo', 'class='=>'?class-string'], 'GlobIterator::getPathname' => ['string'], 'GlobIterator::getPerms' => ['int'], -'GlobIterator::getRealPath' => ['string|false'], +'GlobIterator::getRealPath' => ['non-falsy-string|false'], 'GlobIterator::getSize' => ['int'], 'GlobIterator::getType' => ['string|false'], 'GlobIterator::isDir' => ['bool'], @@ -9722,8 +9722,8 @@ 'readline_read_history' => ['bool', 'filename='=>'?string'], 'readline_redisplay' => ['void'], 'readline_write_history' => ['bool', 'filename='=>'?string'], -'readlink' => ['string|false', 'path'=>'string'], -'realpath' => ['string|false', 'path'=>'string'], +'readlink' => ['non-falsy-string|false', 'path'=>'string'], +'realpath' => ['non-falsy-string|false', 'path'=>'string'], 'realpath_cache_get' => ['array'], 'realpath_cache_size' => ['int'], 'recode' => ['string', 'request'=>'string', 'string'=>'string'], @@ -9811,7 +9811,7 @@ 'RecursiveDirectoryIterator::getPathInfo' => ['?SplFileInfo', 'class='=>'?class-string'], 'RecursiveDirectoryIterator::getPathname' => ['string'], 'RecursiveDirectoryIterator::getPerms' => ['int'], -'RecursiveDirectoryIterator::getRealPath' => ['string'], +'RecursiveDirectoryIterator::getRealPath' => ['non-falsy-string'], 'RecursiveDirectoryIterator::getSize' => ['int'], 'RecursiveDirectoryIterator::getSubPath' => ['string'], 'RecursiveDirectoryIterator::getSubPathname' => ['string'], @@ -12238,7 +12238,7 @@ 'SplFileInfo::getPathInfo' => ['SplFileInfo|null', 'class='=>'?class-string'], 'SplFileInfo::getPathname' => ['string'], 'SplFileInfo::getPerms' => ['int|false'], -'SplFileInfo::getRealPath' => ['string|false'], +'SplFileInfo::getRealPath' => ['non-falsy-string|false'], 'SplFileInfo::getSize' => ['int|false'], 'SplFileInfo::getType' => ['string|false'], 'SplFileInfo::isDir' => ['bool'], @@ -12288,7 +12288,7 @@ 'SplFileObject::getPathInfo' => ['SplFileInfo|null', 'class='=>'?class-string'], 'SplFileObject::getPathname' => ['string'], 'SplFileObject::getPerms' => ['int|false'], -'SplFileObject::getRealPath' => ['false|string'], +'SplFileObject::getRealPath' => ['false|non-falsy-string'], 'SplFileObject::getSize' => ['int|false'], 'SplFileObject::getType' => ['string|false'], 'SplFileObject::hasChildren' => ['false'], @@ -12475,7 +12475,7 @@ 'SplTempFileObject::getPathInfo' => ['SplFileInfo|null', 'class='=>'?class-string'], 'SplTempFileObject::getPathname' => ['string'], 'SplTempFileObject::getPerms' => ['int|false'], -'SplTempFileObject::getRealPath' => ['false|string'], +'SplTempFileObject::getRealPath' => ['false|non-falsy-string'], 'SplTempFileObject::getSize' => ['int|false'], 'SplTempFileObject::getType' => ['string|false'], 'SplTempFileObject::hasChildren' => ['false'], @@ -12690,8 +12690,8 @@ 'ssh2_sftp_chmod' => ['bool', 'sftp'=>'resource', 'filename'=>'string', 'mode'=>'int'], 'ssh2_sftp_lstat' => ['array{0: int, 1: int, 2: int, 3: int, 4: int, 5: int, 6: int, 7: int, 8: int, 9: int, 10: int, 11: int, 12: int, dev: int, ino: int, mode: int, nlink: int, uid: int, gid: int, rdev: int, size: int, atime: int, mtime: int, ctime: int, blksize: int, blocks: int}|false', 'sftp'=>'resource', 'path'=>'string'], 'ssh2_sftp_mkdir' => ['bool', 'sftp'=>'resource', 'dirname'=>'string', 'mode='=>'int', 'recursive='=>'bool'], -'ssh2_sftp_readlink' => ['string|false', 'sftp'=>'resource', 'link'=>'string'], -'ssh2_sftp_realpath' => ['string|false', 'sftp'=>'resource', 'filename'=>'string'], +'ssh2_sftp_readlink' => ['non-falsy-string|false', 'sftp'=>'resource', 'link'=>'string'], +'ssh2_sftp_realpath' => ['non-falsy-string|false', 'sftp'=>'resource', 'filename'=>'string'], 'ssh2_sftp_rename' => ['bool', 'sftp'=>'resource', 'from'=>'string', 'to'=>'string'], 'ssh2_sftp_rmdir' => ['bool', 'sftp'=>'resource', 'dirname'=>'string'], 'ssh2_sftp_stat' => ['array{0: int, 1: int, 2: int, 3: int, 4: int, 5: int, 6: int, 7: int, 8: int, 9: int, 10: int, 11: int, 12: int, dev: int, ino: int, mode: int, nlink: int, uid: int, gid: int, rdev: int, size: int, atime: int, mtime: int, ctime: int, blksize: int, blocks: int}|false', 'sftp'=>'resource', 'path'=>'string'], diff --git a/dictionaries/CallMap_historical.php b/dictionaries/CallMap_historical.php index 889e1b4fb12..b9dc4b7b545 100644 --- a/dictionaries/CallMap_historical.php +++ b/dictionaries/CallMap_historical.php @@ -877,7 +877,7 @@ 'DirectoryIterator::getPathInfo' => ['?SplFileInfo', 'class='=>'class-string'], 'DirectoryIterator::getPathname' => ['string'], 'DirectoryIterator::getPerms' => ['int'], - 'DirectoryIterator::getRealPath' => ['string'], + 'DirectoryIterator::getRealPath' => ['non-falsy-string'], 'DirectoryIterator::getSize' => ['int'], 'DirectoryIterator::getType' => ['string'], 'DirectoryIterator::isDir' => ['bool'], @@ -1507,7 +1507,7 @@ 'FilesystemIterator::getPathInfo' => ['?SplFileInfo', 'class='=>'class-string'], 'FilesystemIterator::getPathname' => ['string'], 'FilesystemIterator::getPerms' => ['int'], - 'FilesystemIterator::getRealPath' => ['string'], + 'FilesystemIterator::getRealPath' => ['non-falsy-string'], 'FilesystemIterator::getSize' => ['int'], 'FilesystemIterator::getType' => ['string'], 'FilesystemIterator::isDir' => ['bool'], @@ -1762,7 +1762,7 @@ 'GlobIterator::getPathInfo' => ['?SplFileInfo', 'class='=>'class-string'], 'GlobIterator::getPathname' => ['string'], 'GlobIterator::getPerms' => ['int'], - 'GlobIterator::getRealPath' => ['string|false'], + 'GlobIterator::getRealPath' => ['non-falsy-string|false'], 'GlobIterator::getSize' => ['int'], 'GlobIterator::getType' => ['string|false'], 'GlobIterator::isDir' => ['bool'], @@ -5155,7 +5155,7 @@ 'RecursiveDirectoryIterator::getPathInfo' => ['?SplFileInfo', 'class='=>'class-string'], 'RecursiveDirectoryIterator::getPathname' => ['string'], 'RecursiveDirectoryIterator::getPerms' => ['int'], - 'RecursiveDirectoryIterator::getRealPath' => ['string'], + 'RecursiveDirectoryIterator::getRealPath' => ['non-falsy-string'], 'RecursiveDirectoryIterator::getSize' => ['int'], 'RecursiveDirectoryIterator::getSubPath' => ['string'], 'RecursiveDirectoryIterator::getSubPathname' => ['string'], @@ -7481,7 +7481,7 @@ 'SplFileInfo::getPathInfo' => ['SplFileInfo|null', 'class='=>'class-string'], 'SplFileInfo::getPathname' => ['string'], 'SplFileInfo::getPerms' => ['int|false'], - 'SplFileInfo::getRealPath' => ['string|false'], + 'SplFileInfo::getRealPath' => ['non-falsy-string|false'], 'SplFileInfo::getSize' => ['int|false'], 'SplFileInfo::getType' => ['string|false'], 'SplFileInfo::isDir' => ['bool'], @@ -7532,7 +7532,7 @@ 'SplFileObject::getPathInfo' => ['SplFileInfo|null', 'class='=>'class-string'], 'SplFileObject::getPathname' => ['string'], 'SplFileObject::getPerms' => ['int|false'], - 'SplFileObject::getRealPath' => ['false|string'], + 'SplFileObject::getRealPath' => ['false|non-falsy-string'], 'SplFileObject::getSize' => ['int|false'], 'SplFileObject::getType' => ['string|false'], 'SplFileObject::hasChildren' => ['false'], @@ -7723,7 +7723,7 @@ 'SplTempFileObject::getPathInfo' => ['SplFileInfo|null', 'class='=>'class-string'], 'SplTempFileObject::getPathname' => ['string'], 'SplTempFileObject::getPerms' => ['int|false'], - 'SplTempFileObject::getRealPath' => ['false|string'], + 'SplTempFileObject::getRealPath' => ['false|non-falsy-string'], 'SplTempFileObject::getSize' => ['int|false'], 'SplTempFileObject::getType' => ['string|false'], 'SplTempFileObject::hasChildren' => ['false'], @@ -13718,8 +13718,8 @@ 'readline_read_history' => ['bool', 'filename='=>'string'], 'readline_redisplay' => ['void'], 'readline_write_history' => ['bool', 'filename='=>'string'], - 'readlink' => ['string|false', 'path'=>'string'], - 'realpath' => ['string|false', 'path'=>'string'], + 'readlink' => ['non-falsy-string|false', 'path'=>'string'], + 'realpath' => ['non-falsy-string|false', 'path'=>'string'], 'realpath_cache_get' => ['array'], 'realpath_cache_size' => ['int'], 'recode' => ['string', 'request'=>'string', 'string'=>'string'], @@ -14120,8 +14120,8 @@ 'ssh2_sftp_chmod' => ['bool', 'sftp'=>'resource', 'filename'=>'string', 'mode'=>'int'], 'ssh2_sftp_lstat' => ['array{0: int, 1: int, 2: int, 3: int, 4: int, 5: int, 6: int, 7: int, 8: int, 9: int, 10: int, 11: int, 12: int, dev: int, ino: int, mode: int, nlink: int, uid: int, gid: int, rdev: int, size: int, atime: int, mtime: int, ctime: int, blksize: int, blocks: int}|false', 'sftp'=>'resource', 'path'=>'string'], 'ssh2_sftp_mkdir' => ['bool', 'sftp'=>'resource', 'dirname'=>'string', 'mode='=>'int', 'recursive='=>'bool'], - 'ssh2_sftp_readlink' => ['string|false', 'sftp'=>'resource', 'link'=>'string'], - 'ssh2_sftp_realpath' => ['string|false', 'sftp'=>'resource', 'filename'=>'string'], + 'ssh2_sftp_readlink' => ['non-falsy-string|false', 'sftp'=>'resource', 'link'=>'string'], + 'ssh2_sftp_realpath' => ['non-falsy-string|false', 'sftp'=>'resource', 'filename'=>'string'], 'ssh2_sftp_rename' => ['bool', 'sftp'=>'resource', 'from'=>'string', 'to'=>'string'], 'ssh2_sftp_rmdir' => ['bool', 'sftp'=>'resource', 'dirname'=>'string'], 'ssh2_sftp_stat' => ['array{0: int, 1: int, 2: int, 3: int, 4: int, 5: int, 6: int, 7: int, 8: int, 9: int, 10: int, 11: int, 12: int, dev: int, ino: int, mode: int, nlink: int, uid: int, gid: int, rdev: int, size: int, atime: int, mtime: int, ctime: int, blksize: int, blocks: int}|false', 'sftp'=>'resource', 'path'=>'string'], From 41ce826f6dd8595bfa7e08470ee515bdb20e3cd1 Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:58:04 +0100 Subject: [PATCH 7/9] improve file_put_contents return type --- dictionaries/CallMap.php | 2 +- dictionaries/CallMap_historical.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dictionaries/CallMap.php b/dictionaries/CallMap.php index 048c7287da7..e79081aca8f 100644 --- a/dictionaries/CallMap.php +++ b/dictionaries/CallMap.php @@ -2792,7 +2792,7 @@ 'file' => ['list|false', 'filename'=>'string', 'flags='=>'int', 'context='=>'resource'], 'file_exists' => ['bool', 'filename'=>'string'], 'file_get_contents' => ['string|false', 'filename'=>'string', 'use_include_path='=>'bool', 'context='=>'?resource', 'offset='=>'int', 'length='=>'?int'], -'file_put_contents' => ['int|false', 'filename'=>'string', 'data'=>'string|resource|array', 'flags='=>'int', 'context='=>'resource'], +'file_put_contents' => ['int<0, max>|false', 'filename'=>'string', 'data'=>'string|resource|array', 'flags='=>'int', 'context='=>'resource'], 'fileatime' => ['int|false', 'filename'=>'string'], 'filectime' => ['int|false', 'filename'=>'string'], 'filegroup' => ['int|false', 'filename'=>'string'], diff --git a/dictionaries/CallMap_historical.php b/dictionaries/CallMap_historical.php index b9dc4b7b545..80f6771ae84 100644 --- a/dictionaries/CallMap_historical.php +++ b/dictionaries/CallMap_historical.php @@ -10417,7 +10417,7 @@ 'file' => ['list|false', 'filename'=>'string', 'flags='=>'int', 'context='=>'resource'], 'file_exists' => ['bool', 'filename'=>'string'], 'file_get_contents' => ['string|false', 'filename'=>'string', 'use_include_path='=>'bool', 'context='=>'?resource', 'offset='=>'int', 'length='=>'int'], - 'file_put_contents' => ['int|false', 'filename'=>'string', 'data'=>'string|resource|array', 'flags='=>'int', 'context='=>'resource'], + 'file_put_contents' => ['int<0, max>|false', 'filename'=>'string', 'data'=>'string|resource|array', 'flags='=>'int', 'context='=>'resource'], 'fileatime' => ['int|false', 'filename'=>'string'], 'filectime' => ['int|false', 'filename'=>'string'], 'filegroup' => ['int|false', 'filename'=>'string'], From ee7187c8d652c3c40ff4319a5a42f0aaa27c2a54 Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Sun, 4 Feb 2024 11:51:57 +0100 Subject: [PATCH 8/9] directory_separator optional wrong --- src/Psalm/Config.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Psalm/Config.php b/src/Psalm/Config.php index bebf471599c..3e440e3809b 100644 --- a/src/Psalm/Config.php +++ b/src/Psalm/Config.php @@ -1817,7 +1817,13 @@ private function getPluginClassForPath(Codebase $codebase, string $path, string public function shortenFileName(string $to): string { if (!is_file($to)) { - return preg_replace('/^' . preg_quote($this->base_dir . DIRECTORY_SEPARATOR, '/') . '?/', '', $to, 1); + // if cwd is the root directory it will be just the directory separator - trim it off first + return preg_replace( + '/^' . preg_quote(rtrim($this->base_dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR, '/') . '/', + '', + $to, + 1, + ); } $from = $this->base_dir; From 2008ea078a89061713010197df7a574ef3ab89f2 Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Mon, 5 Feb 2024 08:19:23 +0100 Subject: [PATCH 9/9] code review add die to forbidden functions for psalm itself --- psalm.xml.dist | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/psalm.xml.dist b/psalm.xml.dist index 816cdc02e87..0843b86bcc9 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -173,4 +173,8 @@ + + + +