diff --git a/composer.json b/composer.json index 5839a98..fb8ebe8 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ "nikic/php-parser": "^4.13", "php-stubs/generator": "^0.8.3", "phpdocumentor/reflection-docblock": "^5.4.1", - "phpstan/phpstan": "^1.10.49", + "phpstan/phpstan": "^1.11", "phpunit/phpunit": "^9.5", "szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^1.1.1", "wp-coding-standards/wpcs": "3.1.0 as 2.3.0" diff --git a/functionMap.php b/functionMap.php index 69e0b24..35ed641 100644 --- a/functionMap.php +++ b/functionMap.php @@ -36,7 +36,7 @@ '__return_empty_string' => ["''"], '__return_zero' => ['0'], '_wp_json_sanity_check' => ['T', '@phpstan-template' => 'T', 'value' => 'T', 'depth' => 'int<1, max>'], - '_get_list_table' => ["(\$class_name is 'WP_Posts_List_Table'|'WP_Media_List_Table'|'WP_Terms_List_Table'|'WP_Users_List_Table'|'WP_Comments_List_Table'|'WP_Post_Comments_List_Table'|'WP_Links_List_Table'|'WP_Plugin_Install_List_Table'|'WP_Themes_List_Table'|'WP_Theme_Install_List_Table'|'WP_Plugins_List_Table'|'WP_Application_Passwords_List_Table'|'WP_MS_Sites_List_Table'|'WP_MS_Users_List_Table'|'WP_MS_Themes_List_Table'|'WP_Privacy_Data_Export_Requests_List_Table'|'WP_Privacy_Data_Removal_Requests_List_Table' ? T : false)", '@phpstan-template' => 'T', 'class_name' => 'class-string', 'args' => 'array{screen?: string}'], + '_get_list_table' => ["(\$class_name is 'WP_Posts_List_Table'|'WP_Media_List_Table'|'WP_Terms_List_Table'|'WP_Users_List_Table'|'WP_Comments_List_Table'|'WP_Post_Comments_List_Table'|'WP_Links_List_Table'|'WP_Plugin_Install_List_Table'|'WP_Themes_List_Table'|'WP_Theme_Install_List_Table'|'WP_Plugins_List_Table'|'WP_Application_Passwords_List_Table'|'WP_MS_Sites_List_Table'|'WP_MS_Users_List_Table'|'WP_MS_Themes_List_Table'|'WP_Privacy_Data_Export_Requests_List_Table'|'WP_Privacy_Data_Removal_Requests_List_Table' ? new : false)", '@phpstan-template T' => 'of string', 'class_name' => 'T', 'args' => 'array{screen?: string}'], 'absint' => ['($maybeint is T&int<0, max> ? T : ($maybeint is int ? int<1, max> : ($maybeint is empty ? 0 : ($maybeint is numeric-string ? int<0, max> : ($maybeint is string ? 0 : ($maybeint is true|non-empty-array ? 1 : ($maybeint is bool ? 0|1 : int<0, max>)))))))', '@phpstan-template T' => 'of int', 'maybeint' => 'T|scalar|array|resource|null'], 'addslashes_gpc' => ['T', '@phpstan-template' => 'T', 'gpc' => 'T'], 'add_submenu_page' => [null, 'callback' => "''|callable"], diff --git a/tests/data/_get_list_table.php b/tests/data/_get_list_table.php index ec355b6..72c9ab0 100644 --- a/tests/data/_get_list_table.php +++ b/tests/data/_get_list_table.php @@ -7,8 +7,16 @@ use function _get_list_table; use function PHPStan\Testing\assertType; -assertType('false', _get_list_table('Not_WP_List_Table')); +// A non-class-string +assertType('false', _get_list_table('string')); +// A class-string that is not class-string +assertType('false', _get_list_table('WP_Post')); + +// WP_List_Table itself +assertType('false', _get_list_table('WP_List_Table')); + +// Core WP_List_Table classes assertType('WP_Posts_List_Table', _get_list_table('WP_Posts_List_Table')); assertType('WP_Media_List_Table', _get_list_table('WP_Media_List_Table')); assertType('WP_Terms_List_Table', _get_list_table('WP_Terms_List_Table')); @@ -18,7 +26,6 @@ assertType('WP_Links_List_Table', _get_list_table('WP_Links_List_Table')); assertType('WP_Plugin_Install_List_Table', _get_list_table('WP_Plugin_Install_List_Table')); assertType('WP_Themes_List_Table', _get_list_table('WP_Themes_List_Table')); -assertType('WP_Theme_Install_List_Table', _get_list_table('WP_Theme_Install_List_Table')); assertType('WP_Plugins_List_Table', _get_list_table('WP_Plugins_List_Table')); assertType('WP_Application_Passwords_List_Table', _get_list_table('WP_Application_Passwords_List_Table')); assertType('WP_MS_Sites_List_Table', _get_list_table('WP_MS_Sites_List_Table')); @@ -26,3 +33,18 @@ assertType('WP_MS_Themes_List_Table', _get_list_table('WP_MS_Themes_List_Table')); assertType('WP_Privacy_Data_Export_Requests_List_Table', _get_list_table('WP_Privacy_Data_Export_Requests_List_Table')); assertType('WP_Privacy_Data_Removal_Requests_List_Table', _get_list_table('WP_Privacy_Data_Removal_Requests_List_Table')); + +// Union of core WP_List_Table classes +assertType('WP_Media_List_Table|WP_Posts_List_Table', _get_list_table(isset($_GET['foo']) ? 'WP_Posts_List_Table' : 'WP_Media_List_Table')); + +// Union of core WP_List_Table class and class that is not a subclass of WP_List_Table +assertType('WP_Posts_List_Table|false', _get_list_table(isset($_GET['foo']) ? 'WP_Posts_List_Table' : 'WP_Post')); + +// WP_Post_Comments_List_Table is generalized WP_Comments_List_Table +assertType('WP_Comments_List_Table', _get_list_table(isset($_GET['foo']) ? 'WP_Comments_List_Table' : 'WP_Post_Comments_List_Table')); + +// WP_Theme_Install_List_Table is generalized to WP_Themes_List_Table +assertType('WP_Themes_List_Table', _get_list_table(isset($_GET['foo']) ? 'WP_Themes_List_Table' : 'WP_Theme_Install_List_Table')); + +// Unknown string +assertType('WP_Application_Passwords_List_Table|WP_Comments_List_Table|WP_Links_List_Table|WP_Media_List_Table|WP_MS_Sites_List_Table|WP_MS_Themes_List_Table|WP_MS_Users_List_Table|WP_Plugin_Install_List_Table|WP_Plugins_List_Table|WP_Posts_List_Table|WP_Privacy_Data_Export_Requests_List_Table|WP_Privacy_Data_Removal_Requests_List_Table|WP_Terms_List_Table|WP_Themes_List_Table|WP_Users_List_Table|false', _get_list_table(Faker::string())); diff --git a/wordpress-stubs.php b/wordpress-stubs.php index 88476e1..84d1752 100644 --- a/wordpress-stubs.php +++ b/wordpress-stubs.php @@ -82014,10 +82014,10 @@ function wp_get_popular_importers() * @param string $class_name The type of the list table, which is the class name. * @param array $args Optional. Arguments to pass to the class. Accepts 'screen'. * @return WP_List_Table|false List table object on success, false if the class does not exist. - * @phpstan-template T - * @phpstan-param class-string $class_name + * @phpstan-template T of string + * @phpstan-param T $class_name * @phpstan-param array{screen?: string} $args - * @phpstan-return ($class_name is 'WP_Posts_List_Table'|'WP_Media_List_Table'|'WP_Terms_List_Table'|'WP_Users_List_Table'|'WP_Comments_List_Table'|'WP_Post_Comments_List_Table'|'WP_Links_List_Table'|'WP_Plugin_Install_List_Table'|'WP_Themes_List_Table'|'WP_Theme_Install_List_Table'|'WP_Plugins_List_Table'|'WP_Application_Passwords_List_Table'|'WP_MS_Sites_List_Table'|'WP_MS_Users_List_Table'|'WP_MS_Themes_List_Table'|'WP_Privacy_Data_Export_Requests_List_Table'|'WP_Privacy_Data_Removal_Requests_List_Table' ? T : false) + * @phpstan-return ($class_name is 'WP_Posts_List_Table'|'WP_Media_List_Table'|'WP_Terms_List_Table'|'WP_Users_List_Table'|'WP_Comments_List_Table'|'WP_Post_Comments_List_Table'|'WP_Links_List_Table'|'WP_Plugin_Install_List_Table'|'WP_Themes_List_Table'|'WP_Theme_Install_List_Table'|'WP_Plugins_List_Table'|'WP_Application_Passwords_List_Table'|'WP_MS_Sites_List_Table'|'WP_MS_Users_List_Table'|'WP_MS_Themes_List_Table'|'WP_Privacy_Data_Export_Requests_List_Table'|'WP_Privacy_Data_Removal_Requests_List_Table' ? new : false) */ function _get_list_table($class_name, $args = array()) {