From b4126326eb19d4983e757d6ddd51997e057dd6fc Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Mon, 3 Jul 2023 22:28:25 +0200 Subject: [PATCH] make stubbed constant types configurable with comment Fix https://github.com/vimeo/psalm/issues/4024 --- .../Reflector/ExpressionScanner.php | 26 +++++++++++- tests/StubTest.php | 42 +++++++++++++++++++ .../stubs/constant_var_comment.phpstub | 3 ++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/stubs/constant_var_comment.phpstub diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php b/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php index e0add3a00e4..696b7497d70 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php @@ -6,8 +6,10 @@ use Psalm\Aliases; use Psalm\Codebase; use Psalm\Config; +use Psalm\Exception\DocblockParseException; use Psalm\Exception\FileIncludeException; use Psalm\Internal\Analyzer\ClassLikeAnalyzer; +use Psalm\Internal\Analyzer\CommentAnalyzer; use Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer; use Psalm\Internal\Analyzer\Statements\Expression\Fetch\ConstFetchAnalyzer; use Psalm\Internal\Analyzer\Statements\Expression\IncludeAnalyzer; @@ -151,7 +153,29 @@ private static function registerClassMapFunctionCall( $type_provider, $second_arg_value, $aliases, - ) ?? Type::getMixed(); + ); + + // allow docblocks to override the declared value to make constants in stubs configurable + $doc_comment = $second_arg_value->getDocComment(); + if ($doc_comment) { + try { + $var_comments = CommentAnalyzer::getTypeFromComment($doc_comment, $file_scanner, $aliases); + foreach ($var_comments as $var_comment) { + if ($var_comment->type) { + $const_type = $var_comment->type; + } + + // only check the first @var comment + break; + } + } catch (DocblockParseException $e) { + // do nothing + } + } + + if ($const_type === null) { + $const_type = Type::getMixed(); + } $config = Config::getInstance(); diff --git a/tests/StubTest.php b/tests/StubTest.php index a86f148686c..c52239d68ee 100644 --- a/tests/StubTest.php +++ b/tests/StubTest.php @@ -693,6 +693,48 @@ public function testConditionalConstantDefined(): void $this->analyzeFile($file_path, new Context()); } + /** + * @runInSeparateProcess + */ + public function testStubbedConstantVarCommentType(): void + { + $this->project_analyzer = $this->getProjectAnalyzerWithConfig( + TestConfig::loadFromXML( + dirname(__DIR__), + ' + + + + + + + + + ', + ), + ); + + $file_path = getcwd() . '/src/somefile.php'; + + $this->addFile( + $file_path, + 'analyzeFile($file_path, new Context()); + } + /** * @runInSeparateProcess */ diff --git a/tests/fixtures/stubs/constant_var_comment.phpstub b/tests/fixtures/stubs/constant_var_comment.phpstub new file mode 100644 index 00000000000..d747c244652 --- /dev/null +++ b/tests/fixtures/stubs/constant_var_comment.phpstub @@ -0,0 +1,3 @@ +