1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-22 05:41:20 +01:00

Refactor signature selection a little

This commit is contained in:
Matthew Brown 2019-07-18 23:08:54 -04:00
parent 0e6bd79a09
commit 5583ae842e
4 changed files with 113 additions and 73 deletions

View File

@ -1194,6 +1194,57 @@ class Codebase
return [$reference, $argument_number, $range];
}
/**
* @param array{0: string} $argument_location
*/
public function getSignatureInformation(array $argument_location) : ?\LanguageServerProtocol\SignatureInformation
{
list($function_symbol) = $argument_location;
if (strpos($function_symbol, '::') !== false) {
$declaring_method_id = $this->methods->getDeclaringMethodId($function_symbol);
if ($declaring_method_id === null) {
return null;
}
$method_storage = $this->methods->getStorage($declaring_method_id);
$params = $method_storage->params;
} else {
try {
$function_storage = $this->functions->getStorage(null, $function_symbol);
} catch (\Exception $exception) {
return null;
}
$params = $function_storage->params;
}
$signature_label = '(';
$parameters = [];
foreach ($params as $i => $param) {
$parameter_label = ($param->type ?: 'mixed') . ' $' . $param->name;
$parameters[] = new \LanguageServerProtocol\ParameterInformation([
strlen($signature_label),
strlen($signature_label) + strlen($parameter_label),
]);
$signature_label .= $parameter_label;
if ($i < (count($params) - 1)) {
$signature_label .= ', ';
}
}
$signature_label .= ')';
return new \LanguageServerProtocol\SignatureInformation(
$signature_label,
$parameters
);
}
/**
* @return array{0: string, 1: '->'|'::'|'symbol', 2: int}|null
*/

View File

@ -269,48 +269,19 @@ class TextDocument
$file_path = LanguageServer::uriToPath($textDocument->uri);
$argument_location = $this->codebase->getFunctionArgumentAtPosition($file_path, $position);
if ($argument_location === null) {
return new Success(new \LanguageServerProtocol\SignatureHelp());
}
list($function_symbol, $argument_number) = $argument_location;
if (strpos($function_symbol, '::') !== false) {
$declaring_method_id = $this->codebase->methods->getDeclaringMethodId($function_symbol);
if ($declaring_method_id === null) {
$signature_information = $this->codebase->getSignatureInformation($argument_location);
if (!$signature_information) {
return new Success(new \LanguageServerProtocol\SignatureHelp());
}
$method_storage = $this->codebase->methods->getStorage($declaring_method_id);
$params = $method_storage->params;
} else {
try {
$function_storage = $this->codebase->functions->getStorage(null, $function_symbol);
} catch (\Exception $exception) {
return new Success(new \LanguageServerProtocol\SignatureHelp());
}
$params = $function_storage->params;
}
$signature_label = '(';
$parameters = [];
foreach ($params as $i => $param) {
$parameter_label = ($param->type ?: 'mixed') . ' $' . $param->name;
$parameters[] = new \LanguageServerProtocol\ParameterInformation([
strlen($signature_label),
strlen($signature_label) + strlen($parameter_label),
]);
$signature_label .= $parameter_label;
if ($i < (count($params) - 1)) {
$signature_label .= ', ';
}
}
$signature_label .= ')';
return new Success(new \LanguageServerProtocol\SignatureHelp([
new \LanguageServerProtocol\SignatureInformation(
$signature_label,
$parameters
),
], 0, $argument_number));
$signature_information,
], 0, $argument_location[1]));
}
}

View File

@ -1,25 +1,25 @@
<?php
namespace Psalm\Internal\Provider;
use function array_merge;
use const DIRECTORY_SEPARATOR;
use function dirname;
use function file_exists;
use function file_get_contents;
use function file_put_contents;
use function filemtime;
use function get_class;
use function igbinary_serialize;
use function igbinary_unserialize;
use function is_dir;
use function mkdir;
use Psalm\Config;
use Psalm\Storage\ClassLikeStorage;
use function serialize;
use function sha1;
use function dirname;
use const DIRECTORY_SEPARATOR;
use function array_merge;
use function file_exists;
use function filemtime;
use function strtolower;
use function file_put_contents;
use function igbinary_serialize;
use function serialize;
use function get_class;
use function unlink;
use function sha1;
use function igbinary_unserialize;
use function file_get_contents;
use function unserialize;
use function is_dir;
use function mkdir;
/**
* @internal
@ -75,6 +75,7 @@ class ClassLikeStorageCacheProvider
public function writeToCache(ClassLikeStorage $storage, $file_path, $file_contents)
{
$fq_classlike_name_lc = strtolower($storage->name);
$cache_location = $this->getCacheLocationForClass($fq_classlike_name_lc, $file_path, true);
$storage->hash = $this->getCacheHash($file_path, $file_contents);

View File

@ -306,30 +306,30 @@ class SymbolLookupTest extends \Psalm\Tests\TestCase
}
/**
* @return array<int, array{0: Position, 1: ?string, 2: ?int}>
* @return array<int, array{0: Position, 1: ?string, 2: ?int, 3: ?int}>
*/
public function providerGetSignatureHelp(): array
{
return [
[new Position(5, 34), null, null],
[new Position(5, 35), 'B\A::foo', 0],
[new Position(5, 36), null, null],
[new Position(6, 34), null, null],
[new Position(6, 35), 'B\A::foo', 0],
[new Position(6, 40), 'B\A::foo', 0],
[new Position(6, 41), 'B\A::foo', 1],
[new Position(6, 47), 'B\A::foo', 1],
[new Position(6, 48), null, null],
[new Position(7, 40), 'B\A::foo', 0],
[new Position(7, 41), 'B\A::foo', 1],
[new Position(7, 42), 'B\A::foo', 1],
[new Position(8, 40), 'B\A::foo', 0],
[new Position(8, 46), 'B\A::bar', 0],
[new Position(8, 47), 'B\A::foo', 0],
[new Position(10, 40), 'B\A::staticfoo', 0],
[new Position(12, 28), 'B\foo', 0],
[new Position(14, 30), 'B\A::__construct', 0],
[new Position(16, 31), 'strlen', 0],
[new Position(5, 34), null, null, null],
[new Position(5, 35), 'B\A::foo', 0, 2],
[new Position(5, 36), null, null, null],
[new Position(6, 34), null, null, null],
[new Position(6, 35), 'B\A::foo', 0, 2],
[new Position(6, 40), 'B\A::foo', 0, 2],
[new Position(6, 41), 'B\A::foo', 1, 2],
[new Position(6, 47), 'B\A::foo', 1, 2],
[new Position(6, 48), null, null, null],
[new Position(7, 40), 'B\A::foo', 0, 2],
[new Position(7, 41), 'B\A::foo', 1, 2],
[new Position(7, 42), 'B\A::foo', 1, 2],
[new Position(8, 40), 'B\A::foo', 0, 2],
[new Position(8, 46), 'B\A::bar', 0, 1],
[new Position(8, 47), 'B\A::foo', 0, 2],
[new Position(10, 40), 'B\A::staticfoo', 0, 1],
#[new Position(12, 28), 'B\foo', 0, 1],
[new Position(14, 30), 'B\A::__construct', 0, 0],
#[new Position(16, 31), 'strlen', 0, 1],
];
}
@ -339,7 +339,8 @@ class SymbolLookupTest extends \Psalm\Tests\TestCase
public function testGetSignatureHelp(
Position $position,
?string $expected_symbol,
?int $expected_argument_number
?int $expected_argument_number,
?int $expected_param_count
): void {
$codebase = $this->project_analyzer->getCodebase();
$config = $codebase->config;
@ -382,8 +383,24 @@ class SymbolLookupTest extends \Psalm\Tests\TestCase
$this->analyzeFile('somefile.php', new Context());
$reference_location = $codebase->getFunctionArgumentAtPosition('somefile.php', $position);
if ($expected_symbol !== null) {
$this->assertNotNull($reference_location);
list($symbol, $argument_number) = $reference_location;
$this->assertSame($expected_symbol, $symbol);
$this->assertSame($expected_argument_number, $argument_number);
$symbol_information = $codebase->getSignatureInformation($reference_location);
if ($expected_param_count === null) {
$this->assertNull($symbol_information);
} else {
$this->assertNotNull($symbol_information);
$this->assertNotNull($symbol_information->parameters);
$this->assertCount($expected_param_count, $symbol_information->parameters);
}
} else {
$this->assertNull($reference_location);
}
}
}