Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make stubbed constant types configurable with comment #9992

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 25 additions & 1 deletion src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php
Expand Up @@ -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;
Expand Down Expand Up @@ -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();

Expand Down
42 changes: 42 additions & 0 deletions tests/StubTest.php
Expand Up @@ -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__),
'<?xml version="1.0"?>
<psalm
errorLevel="1"
>
<projectFiles>
<directory name="src" />
</projectFiles>

<stubs>
<file name="tests/fixtures/stubs/constant_var_comment.phpstub" />
</stubs>
</psalm>',
),
);

$file_path = getcwd() . '/src/somefile.php';

$this->addFile(
$file_path,
'<?php
/**
* @param non-empty-string $arg
* @return void
*/
function hello($arg) {
echo $arg;
}

hello(FOO_BAR);',
);

$this->analyzeFile($file_path, new Context());
}

/**
* @runInSeparateProcess
*/
Expand Down
3 changes: 3 additions & 0 deletions tests/fixtures/stubs/constant_var_comment.phpstub
@@ -0,0 +1,3 @@
<?php

define('FOO_BAR', /** @var non-empty-string */ 'world');