diff --git a/fixtures/signatureHelp/methodClosed.php b/fixtures/signatureHelp/methodClosed.php index 924cd30..0f0890f 100644 --- a/fixtures/signatureHelp/methodClosed.php +++ b/fixtures/signatureHelp/methodClosed.php @@ -12,4 +12,4 @@ class HelpClass1 } $a = new HelpClass1; -$a->method(); \ No newline at end of file +$a->method(); diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 58bc9e9..bb5fd6c 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -7,6 +7,7 @@ use PhpParser\Node; use PhpParser\PrettyPrinter\Standard as PrettyPrinter; use phpDocumentor\Reflection\{Types, Type, Fqsen, TypeResolver}; use LanguageServer\Protocol\SymbolInformation; +use LanguageServer\Protocol\ParameterInformation; use LanguageServer\Index\ReadableIndex; class DefinitionResolver @@ -134,7 +135,13 @@ class DefinitionResolver $def->parameters = []; if ($node instanceof Node\FunctionLike) { foreach ($node->getParams() as $param) { - $def->parameters[] = $this->prettyPrinter->prettyPrint([$param]); + if (!$param->getAttribute('parentNode')) { + $param->setAttribute('parentNode', $node); + } + $def->parameters[] = new ParameterInformation( + $this->prettyPrinter->prettyPrint([$param]), + $this->getDocumentationFromNode($param) + ); } } return $def; diff --git a/src/Protocol/ParameterInformation.php b/src/Protocol/ParameterInformation.php index 89b5e53..628804a 100644 --- a/src/Protocol/ParameterInformation.php +++ b/src/Protocol/ParameterInformation.php @@ -23,4 +23,14 @@ class ParameterInformation * @var string|null */ public $documentation; + + /** + * @param string $label The label of this signature. Will be shown in the UI. + * @param string|null $documentation The human-readable doc-comment of this signature. + */ + public function __construct(string $label = null, string $documentation = null) + { + $this->label = $label; + $this->documentation = $documentation; + } } diff --git a/src/Protocol/SignatureHelp.php b/src/Protocol/SignatureHelp.php index 407b25a..0e8e934 100644 --- a/src/Protocol/SignatureHelp.php +++ b/src/Protocol/SignatureHelp.php @@ -29,4 +29,16 @@ class SignatureHelp * @var int|null */ public $activeParameter; + + /** + * @param SignatureInformation[] $signatures The signatures. + * @param bool $activeSignature The active signature. + * @param bool $activeParameter The active parameter of the active signature. + */ + public function __construct(array $signatures = [], int $activeSignature = 0, int $activeParameter = 0) + { + $this->signatures = $signatures; + $this->activeSignature = $activeSignature; + $this->activeParameter = $activeParameter; + } } diff --git a/src/Protocol/SignatureInformation.php b/src/Protocol/SignatureInformation.php index 77e152c..e9762c7 100644 --- a/src/Protocol/SignatureInformation.php +++ b/src/Protocol/SignatureInformation.php @@ -31,4 +31,16 @@ class SignatureInformation * @var ParameterInformation[]|null */ public $parameters; + + /** + * @param string $label The label of this signature. Will be shown in the UI. + * @param string|null $documentation The human-readable doc-comment of this signature. + * @param ParameterInformation[] $parameters The parameters of this signature. + */ + public function __construct(string $label = null, string $documentation = null, array $parameters = []) + { + $this->label = $label; + $this->documentation = $documentation; + $this->parameters = $parameters; + } } diff --git a/src/SignatureHelpProvider.php b/src/SignatureHelpProvider.php index b066e68..b2788d1 100644 --- a/src/SignatureHelpProvider.php +++ b/src/SignatureHelpProvider.php @@ -45,9 +45,6 @@ class SignatureHelpProvider */ public function provideSignature(PhpDocument $doc, Position $pos) : SignatureHelp { - $help = new SignatureHelp; - $help->signatures = []; - $handle = fopen('php://temp', 'r+'); fwrite($handle, $doc->getContent()); fseek($handle, 0); @@ -89,7 +86,7 @@ class SignatureHelpProvider if ($node === null) { fclose($handle); - return $help; + return new SignatureHelp; } $params = ''; @@ -138,7 +135,7 @@ class SignatureHelpProvider } else { if (!preg_match('(([a-zA-Z_\x7f-\xff][:a-zA-Z0-9_\x7f-\xff]*)\s*\((.*)$)', $line, $method)) { fclose($handle); - return $help; + return new SignatureHelp; } $def = $this->index->getDefinition($method[1] . '()'); $params = $method[2]; @@ -148,18 +145,8 @@ class SignatureHelpProvider if ($def) { $method = preg_split('(::|->)', str_replace('()', '', $def->fqn), 2); $method = $method[1] ?? $method[0]; - $signature = new SignatureInformation; - $signature->label = $method . '('.implode(', ', $def->parameters).')'; - $signature->documentation = $def->documentation; - $signature->parameters = []; - foreach ($def->parameters as $param) { - $p = new ParameterInformation; - $p->label = $param; - $signature->parameters[] = $p; - } - $help->activeSignature = 0; - $help->activeParameter = 0; $params = ltrim($params, "( "); + $activeParameter = 0; if (strlen(trim($params))) { try { $lex = new \PhpParser\Lexer(); @@ -173,10 +160,10 @@ class SignatureHelpProvider while ($value !== "\0") { $lex->getNextToken($value); if (($value === ")" || $value === ";") && !count($stack)) { - return $help; + return new SignatureHelp; } if ($value === ',' && !count($stack)) { - $help->activeParameter++; + $activeParameter++; } if ($value === '(') { $stack[] = ')'; @@ -189,11 +176,24 @@ class SignatureHelpProvider } catch (\Exception $ignore) { } } - if ($help->activeParameter < count($signature->parameters)) { - $help->signatures[] = $signature; + if ($activeParameter < count($def->parameters)) { + $params = array_map(function ($v) { + return $v->label; + }, $def->parameters); + return new SignatureHelp( + [ + new SignatureInformation( + $method . '('.implode(', ', $params).')', + $def->documentation, + $def->parameters + ) + ], + 0, + $activeParameter + ); } } - return $help; + return new SignatureHelp; } } diff --git a/tests/LanguageServerTest.php b/tests/LanguageServerTest.php index a32c845..2f1a6e2 100644 --- a/tests/LanguageServerTest.php +++ b/tests/LanguageServerTest.php @@ -43,7 +43,7 @@ class LanguageServerTest extends TestCase $serverCapabilities->completionProvider->resolveProvider = false; $serverCapabilities->completionProvider->triggerCharacters = ['$', '>']; $serverCapabilities->signatureHelpProvider = new SignatureHelpOptions; - $serverCapabilities->signatureHelpProvider->triggerCharacters = ['(']; + $serverCapabilities->signatureHelpProvider->triggerCharacters = ['(',',']; $serverCapabilities->xworkspaceReferencesProvider = true; $serverCapabilities->xdefinitionProvider = true; $serverCapabilities->xdependenciesProvider = true; diff --git a/tests/Server/TextDocument/SignatureHelpTest.php b/tests/Server/TextDocument/SignatureHelpTest.php index a6f4620..3814c09 100644 --- a/tests/Server/TextDocument/SignatureHelpTest.php +++ b/tests/Server/TextDocument/SignatureHelpTest.php @@ -53,17 +53,17 @@ class SignatureHelpTest extends TestCase new Position(9, 22) )->wait(); - $help = new SignatureHelp; - $help->signatures = []; - $info = new SignatureInformation; - $help->signatures[] = $info; - $info->label = 'method(string $param = "")'; - $info->parameters = []; - $param = new ParameterInformation; - $info->parameters[] = $param; - $param->label = 'string $param = ""'; - - $this->assertEquals($help, $result); + $this->assertEquals(new SignatureHelp( + [ + new SignatureInformation( + 'method(string $param = "")', + null, + [ + new ParameterInformation('string $param = ""') + ] + ) + ] + ), $result); } public function testMethodClosedReference() @@ -75,17 +75,17 @@ class SignatureHelpTest extends TestCase new Position(14, 11) )->wait(); - $help = new SignatureHelp; - $help->signatures = []; - $info = new SignatureInformation; - $help->signatures[] = $info; - $info->label = 'method(string $param = "")'; - $info->parameters = []; - $param = new ParameterInformation; - $info->parameters[] = $param; - $param->label = 'string $param = ""'; - - $this->assertEquals($help, $result); + $this->assertEquals(new SignatureHelp( + [ + new SignatureInformation( + 'method(string $param = "")', + null, + [ + new ParameterInformation('string $param = ""') + ] + ) + ] + ), $result); } public function testMethodNotClosed() @@ -97,17 +97,17 @@ class SignatureHelpTest extends TestCase new Position(9, 22) )->wait(); - $help = new SignatureHelp; - $help->signatures = []; - $info = new SignatureInformation; - $help->signatures[] = $info; - $info->label = 'method(string $param = "")'; - $info->parameters = []; - $param = new ParameterInformation; - $info->parameters[] = $param; - $param->label = 'string $param = ""'; - - $this->assertEquals($help, $result); + $this->assertEquals(new SignatureHelp( + [ + new SignatureInformation( + 'method(string $param = "")', + null, + [ + new ParameterInformation('string $param = ""') + ] + ) + ] + ), $result); } public function testMethodNotClosedReference() @@ -119,17 +119,17 @@ class SignatureHelpTest extends TestCase new Position(14, 14) )->wait(); - $help = new SignatureHelp; - $help->signatures = []; - $info = new SignatureInformation; - $help->signatures[] = $info; - $info->label = 'method(string $param = "")'; - $info->parameters = []; - $param = new ParameterInformation; - $info->parameters[] = $param; - $param->label = 'string $param = ""'; - - $this->assertEquals($help, $result); + $this->assertEquals(new SignatureHelp( + [ + new SignatureInformation( + 'method(string $param = "")', + null, + [ + new ParameterInformation('string $param = ""') + ] + ) + ] + ), $result); } public function testFuncClosed() @@ -141,17 +141,17 @@ class SignatureHelpTest extends TestCase new Position(6, 10) )->wait(); - $help = new SignatureHelp; - $help->signatures = []; - $info = new SignatureInformation; - $help->signatures[] = $info; - $info->label = 'helpFunc1(int $count = 0)'; - $info->parameters = []; - $param = new ParameterInformation; - $info->parameters[] = $param; - $param->label = 'int $count = 0'; - - $this->assertEquals($help, $result); + $this->assertEquals(new SignatureHelp( + [ + new SignatureInformation( + 'helpFunc1(int $count = 0)', + null, + [ + new ParameterInformation('int $count = 0') + ] + ) + ] + ), $result); } public function testFuncNotClosed() @@ -163,17 +163,17 @@ class SignatureHelpTest extends TestCase new Position(6, 10) )->wait(); - $help = new SignatureHelp; - $help->signatures = []; - $info = new SignatureInformation; - $help->signatures[] = $info; - $info->label = 'helpFunc2(int $count = 0)'; - $info->parameters = []; - $param = new ParameterInformation; - $info->parameters[] = $param; - $param->label = 'int $count = 0'; - - $this->assertEquals($help, $result); + $this->assertEquals(new SignatureHelp( + [ + new SignatureInformation( + 'helpFunc2(int $count = 0)', + null, + [ + new ParameterInformation('int $count = 0') + ] + ) + ] + ), $result); } public function testStaticClosed() @@ -185,17 +185,17 @@ class SignatureHelpTest extends TestCase new Position(9, 19) )->wait(); - $help = new SignatureHelp; - $help->signatures = []; - $info = new SignatureInformation; - $help->signatures[] = $info; - $info->label = 'method(string $param = "")'; - $info->parameters = []; - $param = new ParameterInformation; - $info->parameters[] = $param; - $param->label = 'string $param = ""'; - - $this->assertEquals($help, $result); + $this->assertEquals(new SignatureHelp( + [ + new SignatureInformation( + 'method(string $param = "")', + null, + [ + new ParameterInformation('string $param = ""') + ] + ) + ] + ), $result); } public function testStaticNotClosed() @@ -207,16 +207,16 @@ class SignatureHelpTest extends TestCase new Position(9, 19) )->wait(); - $help = new SignatureHelp; - $help->signatures = []; - $info = new SignatureInformation; - $help->signatures[] = $info; - $info->label = 'method(string $param = "")'; - $info->parameters = []; - $param = new ParameterInformation; - $info->parameters[] = $param; - $param->label = 'string $param = ""'; - - $this->assertEquals($help, $result); + $this->assertEquals(new SignatureHelp( + [ + new SignatureInformation( + 'method(string $param = "")', + null, + [ + new ParameterInformation('string $param = ""') + ] + ) + ] + ), $result); } }