diff --git a/fixtures/signature_help/calls.php b/fixtures/signature_help/calls.php new file mode 100644 index 0000000..2dfc7f2 --- /dev/null +++ b/fixtures/signature_help/calls.php @@ -0,0 +1,55 @@ +foo(); +$t->foo(1, ); +$t->baz(); + +foo(); + +Test::bar(); diff --git a/src/SignatureHelpProvider.php b/src/SignatureHelpProvider.php index 862c0da..1b80b34 100644 --- a/src/SignatureHelpProvider.php +++ b/src/SignatureHelpProvider.php @@ -108,8 +108,10 @@ class SignatureHelpProvider $signatureInformation = new SignatureInformation(); $signatureInformation->label = $label; $signatureInformation->parameters = $params; + $signatureInformation->documentation = $this->definitionResolver->getDocumentationFromNode($node); $signatureHelp = new SignatureHelp(); $signatureHelp->signatures = [$signatureInformation]; + $signatureHelp->activeSignature = 0; $signatureHelp->activeParameter = $activeParam; return $signatureHelp; } diff --git a/tests/Server/TextDocument/SignatureHelpTest.php b/tests/Server/TextDocument/SignatureHelpTest.php new file mode 100644 index 0000000..33a36d7 --- /dev/null +++ b/tests/Server/TextDocument/SignatureHelpTest.php @@ -0,0 +1,191 @@ +loader = new PhpDocumentLoader($contentRetriever, $projectIndex, $definitionResolver); + $this->textDocument = new Server\TextDocument($this->loader, $definitionResolver, $client, $projectIndex); + } + + /** + * @dataProvider signatureHelpProvider + */ + public function testSignatureHelp(Position $position, SignatureHelp $expectedSignature) + { + $callsUri = pathToUri(__DIR__ . '/../../../fixtures/signature_help/calls.php'); + $this->loader->open($callsUri, file_get_contents($callsUri)); + $signatureHelp = $this->textDocument->signatureHelp( + new TextDocumentIdentifier($callsUri), + $position + )->wait(); + $this->assertEquals($expectedSignature, $signatureHelp); + } + + public function signatureHelpProvider(): array + { + return [ + 'member call' => [ + new Position(48, 9), + $this->createSignatureHelp([ + 'label' => '(\\Foo\\SomethingElse $a, int|null $b = null)', + 'documentation' => 'Function doc', + 'parameters' => [ + [ + 'label' => '\\Foo\\SomethingElse $a', + 'documentation' => 'A param with a different doc type', + ], + [ + 'label' => 'int|null $b = null', + 'documentation' => 'Param with default value', + ], + ], + 'activeSignature' => 0, + 'activeParameter' => 0, + ]), + ], + 'member call 2nd param active' => [ + new Position(49, 11), + $this->createSignatureHelp([ + 'label' => '(\\Foo\\SomethingElse $a, int|null $b = null)', + 'documentation' => 'Function doc', + 'parameters' => [ + [ + 'label' => '\\Foo\\SomethingElse $a', + 'documentation' => 'A param with a different doc type', + ], + [ + 'label' => 'int|null $b = null', + 'documentation' => 'Param with default value', + ], + ], + 'activeSignature' => 0, + 'activeParameter' => 1, + ]), + ], + 'method with no params' => [ + new Position(50, 9), + $this->createSignatureHelp([ + 'label' => '()', + 'documentation' => 'Method with no params', + 'parameters' => [], + 'activeSignature' => 0, + 'activeParameter' => 0, + ]), + ], + 'constructor' => [ + new Position(47, 14), + $this->createSignatureHelp([ + 'label' => '(string $first, int $second, \Foo\Test $third)', + 'documentation' => 'Constructor comment goes here', + 'parameters' => [ + [ + 'label' => 'string $first', + 'documentation' => 'First param', + + ], + [ + 'label' => 'int $second', + 'documentation' => 'Second param', + ], + [ + 'label' => '\Foo\Test $third', + 'documentation' => 'Third param with a longer description', + ], + ], + 'activeSignature' => 0, + 'activeParameter' => 0, + ]), + ], + 'global function' => [ + new Position(52, 4), + $this->createSignatureHelp([ + 'label' => '(int $i, bool $b = false)', + 'documentation' => null, + 'parameters' => [ + [ + 'label' => 'int $i', + 'documentation' => 'Global function param one', + ], + [ + 'label' => 'bool $b = false', + 'documentation' => 'Default false param', + ], + ], + 'activeSignature' => 0, + 'activeParameter' => 0, + ]), + ], + 'static method' => [ + new Position(54, 10), + $this->createSignatureHelp([ + 'label' => '(mixed $a)', + 'documentation' => null, + 'parameters' => [ + [ + 'label' => 'mixed $a', + 'documentation' => null, + ], + ], + 'activeSignature' => 0, + 'activeParameter' => 0, + ]), + ], + ]; + } + + private function createSignatureHelp(array $info): SignatureHelp + { + $params = []; + foreach ($info['parameters'] as $param) { + $paramInfo = new ParameterInformation(); + $paramInfo->label = $param['label']; + $paramInfo->documentation = $param['documentation']; + $params[] = $paramInfo; + } + $signature = new SignatureInformation(); + $signature->label = $info['label']; + $signature->documentation = $info['documentation']; + $signature->parameters = $params; + $help = new SignatureHelp(); + $help->signatures = [$signature]; + $help->activeSignature = $info['activeSignature']; + $help->activeParameter = $info['activeParameter']; + return $help; + } +}