1
0
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:
Joe Hoyle 2021-01-28 11:18:28 -05:00 committed by Daniil Gentili
parent 3a50cdef81
commit 6953658961
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
3 changed files with 74 additions and 2 deletions

View File

@ -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());

View File

@ -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) {

View File

@ -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