From c7fc76ec5747d9fb56265c5a8fad62d7ba4ab9a9 Mon Sep 17 00:00:00 2001 From: Jack Worman Date: Thu, 14 Mar 2024 13:12:01 -0400 Subject: [PATCH] MissingClassConstType --- config.xsd | 1 + docs/running_psalm/error_levels.md | 1 + docs/running_psalm/issues.md | 1 + .../issues/MissingClassConstType.md | 21 +++++++ .../Reflector/ClassLikeNodeScanner.php | 19 ++++++ src/Psalm/Issue/MissingClassConstType.php | 11 ++++ tests/Config/PluginTest.php | 38 +++++++----- tests/DocumentationTest.php | 1 + tests/MissingClassConstTypeTest.php | 60 +++++++++++++++++++ 9 files changed, 139 insertions(+), 14 deletions(-) create mode 100644 docs/running_psalm/issues/MissingClassConstType.md create mode 100644 src/Psalm/Issue/MissingClassConstType.php create mode 100644 tests/MissingClassConstTypeTest.php diff --git a/config.xsd b/config.xsd index c15a74e60..9d785d39b 100644 --- a/config.xsd +++ b/config.xsd @@ -313,6 +313,7 @@ + diff --git a/docs/running_psalm/error_levels.md b/docs/running_psalm/error_levels.md index d0edf8c02..155e42671 100644 --- a/docs/running_psalm/error_levels.md +++ b/docs/running_psalm/error_levels.md @@ -232,6 +232,7 @@ Level 5 and above allows a more non-verifiable code, and higher levels are even - [InvalidDocblockParamName](issues/InvalidDocblockParamName.md) - [InvalidFalsableReturnType](issues/InvalidFalsableReturnType.md) - [InvalidStringClass](issues/InvalidStringClass.md) +- [MissingClassConstType](issues/MissingClassConstType.md) - [MissingClosureParamType](issues/MissingClosureParamType.md) - [MissingClosureReturnType](issues/MissingClosureReturnType.md) - [MissingConstructor](issues/MissingConstructor.md) diff --git a/docs/running_psalm/issues.md b/docs/running_psalm/issues.md index ae6834351..384e3703b 100644 --- a/docs/running_psalm/issues.md +++ b/docs/running_psalm/issues.md @@ -113,6 +113,7 @@ - [MismatchingDocblockParamType](issues/MismatchingDocblockParamType.md) - [MismatchingDocblockPropertyType](issues/MismatchingDocblockPropertyType.md) - [MismatchingDocblockReturnType](issues/MismatchingDocblockReturnType.md) + - [MissingClassConstType](issues/MissingClassConstType.md) - [MissingClosureParamType](issues/MissingClosureParamType.md) - [MissingClosureReturnType](issues/MissingClosureReturnType.md) - [MissingConstructor](issues/MissingConstructor.md) diff --git a/docs/running_psalm/issues/MissingClassConstType.md b/docs/running_psalm/issues/MissingClassConstType.md new file mode 100644 index 000000000..c4fa9049f --- /dev/null +++ b/docs/running_psalm/issues/MissingClassConstType.md @@ -0,0 +1,21 @@ +# MissingClassConstType + +Emitted when a class constant doesn't have a declared type. + +```php +codebase->analysis_php_version_id >= 8_03_00 + && $stmt->type === null + ) { + IssueBuffer::maybeAdd( + new MissingClassConstType( + sprintf( + 'Class constant "%s::%s" should have a declared type.', + $storage->name, + $const->name->name, + ), + new CodeLocation($this->file_scanner, $const), + ), + $suppressed_issues, + ); + } + if ($exists) { $existing_constants[$const->name->name] = $constant_storage; } diff --git a/src/Psalm/Issue/MissingClassConstType.php b/src/Psalm/Issue/MissingClassConstType.php new file mode 100644 index 000000000..38f29dbce --- /dev/null +++ b/src/Psalm/Issue/MissingClassConstType.php @@ -0,0 +1,11 @@ +addFile( $file_path, - ' "Psalm\Internal\Analyzer\ProjectAnalyzer", - ]; - }', + sprintf( + <<<'PHP' + "Psalm\Internal\Analyzer\ProjectAnalyzer", + ]; + } + PHP, + $this->project_analyzer->getCodebase()->analysis_php_version_id >= 8_03_00 ? 'array' : '', + ), ); $this->analyzeFile($file_path, new Context()); @@ -173,14 +179,18 @@ class PluginTest extends TestCase $this->addFile( $file_path, - ' \Psalm\Internal\Analyzer\ProjectAnalyzer::class . "::foo", - ]; - }', + sprintf( + <<<'PHP' + \Psalm\Internal\Analyzer\ProjectAnalyzer::class . "::foo", + ]; + } + PHP, + $this->project_analyzer->getCodebase()->analysis_php_version_id >= 8_03_00 ? 'array' : '', + ), ); $this->analyzeFile($file_path, new Context()); diff --git a/tests/DocumentationTest.php b/tests/DocumentationTest.php index aff06fde7..95b2ad3c1 100644 --- a/tests/DocumentationTest.php +++ b/tests/DocumentationTest.php @@ -316,6 +316,7 @@ class DocumentationTest extends TestCase case 'InvalidOverride': case 'MissingOverrideAttribute': + case 'MissingClassConstType': $php_version = '8.3'; break; } diff --git a/tests/MissingClassConstTypeTest.php b/tests/MissingClassConstTypeTest.php new file mode 100644 index 000000000..de413050f --- /dev/null +++ b/tests/MissingClassConstTypeTest.php @@ -0,0 +1,60 @@ += PHP 8.3' => [ + 'code' => <<<'PHP' + [], + 'ignored_issues' => [], + 'php_version' => '8.3', + ], + 'no type; < PHP 8.3' => [ + 'code' => <<<'PHP' + [], + 'ignored_issues' => [], + 'php_version' => '8.2', + ], + ]; + } + + public function providerInvalidCodeParse(): iterable + { + return [ + 'no type; >= PHP 8.3' => [ + 'code' => <<<'PHP' + MissingClassConstType::getIssueType(), + 'error_levels' => [], + 'php_version' => '8.3', + ], + ]; + } +}