mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 12:24:49 +01:00
Add constant fetch to reference map (#5115)
* Add constant fetch to reference map To support showing constant types on hover of constant references, we need to add them to the ref map. * Fix root constants * PHPCBF
This commit is contained in:
parent
3a50cdef81
commit
6953658961
@ -18,7 +18,9 @@ use const PHP_MINOR_VERSION;
|
||||
use PhpParser;
|
||||
use function preg_match;
|
||||
use Psalm\Internal\Analyzer\ProjectAnalyzer;
|
||||
use Psalm\Internal\Analyzer\NamespaceAnalyzer;
|
||||
use Psalm\Internal\Analyzer\Statements\Block\ForeachAnalyzer;
|
||||
use Psalm\Internal\Analyzer\Statements\Expression\Fetch\ConstFetchAnalyzer;
|
||||
use Psalm\Internal\Type\Comparator\UnionTypeComparator;
|
||||
use Psalm\Internal\Codebase\InternalCallMapHandler;
|
||||
use Psalm\Internal\Provider\ClassLikeStorageProvider;
|
||||
@ -39,6 +41,8 @@ use function strrpos;
|
||||
use function strtolower;
|
||||
use function substr;
|
||||
use function substr_count;
|
||||
use function array_pop;
|
||||
use function implode;
|
||||
|
||||
class Codebase
|
||||
{
|
||||
@ -1000,9 +1004,37 @@ class Codebase
|
||||
return '<?php ' . $function->getSignature(true);
|
||||
}
|
||||
|
||||
$storage = $this->classlike_storage_provider->get($symbol);
|
||||
try {
|
||||
$storage = $this->classlike_storage_provider->get($symbol);
|
||||
return '<?php ' . ($storage->abstract ? 'abstract ' : '') . 'class ' . $storage->name;
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
}
|
||||
|
||||
return '<?php ' . ($storage->abstract ? 'abstract ' : '') . 'class ' . $storage->name;
|
||||
if (strpos($symbol, '\\')) {
|
||||
$const_name_parts = explode('\\', $symbol);
|
||||
$const_name = array_pop($const_name_parts);
|
||||
$namespace_name = implode('\\', $const_name_parts);
|
||||
|
||||
$namespace_constants = NamespaceAnalyzer::getConstantsForNamespace(
|
||||
$namespace_name,
|
||||
\ReflectionProperty::IS_PUBLIC
|
||||
);
|
||||
if (isset($namespace_constants[$const_name])) {
|
||||
$type = $namespace_constants[$const_name];
|
||||
return '<?php const ' . $symbol . ' ' . $type;
|
||||
}
|
||||
} else {
|
||||
$file_storage = $this->file_storage_provider->get($file_path);
|
||||
if (isset($file_storage->constants[$symbol])) {
|
||||
return '<?php const ' . $symbol . ' ' . $file_storage->constants[$symbol];
|
||||
}
|
||||
$constant = ConstFetchAnalyzer::getGlobalConstType($this, $symbol, $symbol);
|
||||
|
||||
if ($constant) {
|
||||
return '<?php const ' . $symbol . ' ' . $constant;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (\Exception $e) {
|
||||
error_log($e->getMessage());
|
||||
|
||||
|
@ -58,6 +58,25 @@ class ConstFetchAnalyzer
|
||||
$context
|
||||
);
|
||||
|
||||
$codebase = $statements_analyzer->getCodebase();
|
||||
|
||||
$aliased_constants = $statements_analyzer->getAliases()->constants;
|
||||
if (isset($aliased_constants[$const_name])) {
|
||||
$fq_const_name = $aliased_constants[$const_name];
|
||||
} elseif ($stmt->name instanceof PhpParser\Node\Name\FullyQualified) {
|
||||
$fq_const_name = $const_name;
|
||||
} else {
|
||||
$fq_const_name = Type::getFQCLNFromString($const_name, $statements_analyzer->getAliases());
|
||||
}
|
||||
|
||||
$codebase->analyzer->addNodeReference(
|
||||
$statements_analyzer->getFilePath(),
|
||||
$stmt,
|
||||
$const_type
|
||||
? $fq_const_name
|
||||
: '*' . $fq_const_name
|
||||
);
|
||||
|
||||
if ($const_type) {
|
||||
$statements_analyzer->node_data->setType($stmt, clone $const_type);
|
||||
} elseif ($context->check_consts) {
|
||||
|
@ -44,6 +44,8 @@ class SymbolLookupTest extends \Psalm\Tests\TestCase
|
||||
'<?php
|
||||
namespace B;
|
||||
|
||||
const APPLE = "🍏";
|
||||
|
||||
class A {
|
||||
/** @var int|null */
|
||||
protected $a;
|
||||
@ -81,6 +83,25 @@ class SymbolLookupTest extends \Psalm\Tests\TestCase
|
||||
$this->assertSame('<?php BANANA', $codebase->getSymbolInformation('somefile.php', 'B\A::BANANA'));
|
||||
$this->assertSame("<?php function B\baz(\n int \$a\n) : int", $codebase->getSymbolInformation('somefile.php', 'B\baz()'));
|
||||
$this->assertSame("<?php function B\qux(\n int \$a,\n int \$b\n) : int", $codebase->getSymbolInformation('somefile.php', 'B\qux()'));
|
||||
$this->assertSame("<?php const B\APPLE string", $codebase->getSymbolInformation('somefile.php', 'B\APPLE'));
|
||||
}
|
||||
|
||||
public function testSimpleSymbolLookupGlobalConst(): void
|
||||
{
|
||||
$this->addFile(
|
||||
'somefile.php',
|
||||
'<?php
|
||||
define("BANANA", "🍌");
|
||||
const APPLE = "🍏";'
|
||||
);
|
||||
|
||||
new FileAnalyzer($this->project_analyzer, 'somefile.php', 'somefile.php');
|
||||
|
||||
$codebase = $this->project_analyzer->getCodebase();
|
||||
|
||||
$this->analyzeFile('somefile.php', new Context());
|
||||
$this->assertSame("<?php const APPLE string", $codebase->getSymbolInformation('somefile.php', 'APPLE'));
|
||||
$this->assertSame("<?php const BANANA string", $codebase->getSymbolInformation('somefile.php', 'BANANA'));
|
||||
}
|
||||
|
||||
public function testSimpleSymbolLocation(): void
|
||||
|
Loading…
Reference in New Issue
Block a user