Skip to content

Commit 3b4e0c3

Browse files
committed
added param count
1 parent 16c7560 commit 3b4e0c3

File tree

5 files changed

+114
-106
lines changed

5 files changed

+114
-106
lines changed

fixtures/signatureHelp/funcClosed.php

+1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
function helpFunc1(int $count = 0)
44
{
55
}
6+
67
helpFunc1()

fixtures/signatureHelp/funcNotClosed.php

+3
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,7 @@
33
function helpFunc2(int $count = 0)
44
{
55
}
6+
7+
$a = 1;
8+
69
helpFunc2(

fixtures/signatureHelp/methodNotClosed.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ protected function method(string $param = "")
77
}
88
public function test()
99
{
10-
$this->method(
10+
$this->method(1,1);
1111
}
1212
}
13-
1413
$a = new HelpClass2;
15-
$a->method(1,
14+
$a
15+
->method(
16+
1,
17+
array(),

fixtures/signatureHelp/staticNotClosed.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ public static function method(string $param = "")
77
}
88
}
99

10-
HelpClass4::method(
10+
HelpClass4::method(1, 2, 3
11+
12+
HelpClass4::method(1, 2, 3

src/SignatureHelpProvider.php

+102-102
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33

44
namespace LanguageServer;
55

6+
use PhpParser\ErrorHandler\Collecting;
67
use PhpParser\Node;
78
use LanguageServer\Index\ReadableIndex;
89
use LanguageServer\Protocol\{
10+
Range,
911
Position,
1012
SignatureHelp,
1113
SignatureInformation,
@@ -24,6 +26,16 @@ class SignatureHelpProvider
2426
*/
2527
private $index;
2628

29+
/**
30+
* @var Parser
31+
*/
32+
private $parser;
33+
34+
/**
35+
* @var Parser
36+
*/
37+
private $parserErrorHandler;
38+
2739
/**
2840
* @param DefinitionResolver $definitionResolver
2941
* @param ReadableIndex $index
@@ -32,6 +44,8 @@ public function __construct(DefinitionResolver $definitionResolver, ReadableInde
3244
{
3345
$this->definitionResolver = $definitionResolver;
3446
$this->index = $index;
47+
$this->parser = new Parser;
48+
$this->parserErrorHandler = new Collecting;
3549
}
3650

3751
/**
@@ -41,76 +55,52 @@ public function __construct(DefinitionResolver $definitionResolver, ReadableInde
4155
* @param Position $pos The cursor position
4256
* @return SignatureHelp
4357
*/
44-
public function provideSignature(PhpDocument $doc, Position $pos): SignatureHelp
58+
public function provideSignature(PhpDocument $doc, Position $pos) : SignatureHelp
4559
{
4660
$help = new SignatureHelp;
4761
$help->signatures = [];
4862

49-
$newPos = clone $pos;
50-
$line = explode("\n", $doc->getContent())[$newPos->line];
51-
do {
52-
$newPos->character --;
53-
} while ($newPos->character > 0 && $line[$newPos->character] !== "(");
54-
55-
if (!$newPos->character) {
56-
return $help;
63+
$handle = fopen($doc->getUri(), 'r');
64+
$lines = [];
65+
for ($i = 0; $i < $pos->line; $i++) {
66+
$lines[] = strlen(fgets($handle));
5767
}
58-
$line = substr($line, 0, $newPos->character);
68+
$filePos = ftell($handle) + $pos->character;
69+
$line = substr(fgets($handle), 0, $pos->character);
70+
fseek($handle, 0);
5971

60-
$newPos->character --;
61-
62-
$node = $doc->getNodeAtPosition($newPos);
72+
do {
73+
$node = $doc->getNodeAtPosition($pos);
74+
$pos->character--;
75+
if ($pos->character < 0) {
76+
$pos->line --;
77+
if ($pos->line < 0) {
78+
break;
79+
}
80+
$pos->character = $lines[$pos->line];
81+
}
82+
} while ($node === null);
6383

64-
if ($node instanceof Node\Expr\Error) {
65-
$node = $node->getAttribute('parentNode');
84+
if ($node === null) {
85+
fclose($handle);
86+
return $help;
6687
}
67-
68-
if ($node instanceof Node\Expr\Error) {
88+
$i = 0;
89+
while (!(
90+
$node instanceof Node\Expr\PropertyFetch ||
91+
$node instanceof Node\Expr\MethodCall ||
92+
$node instanceof Node\Expr\FuncCall ||
93+
$node instanceof Node\Expr\ClassConstFetch ||
94+
$node instanceof Node\Expr\StaticCall
95+
) && ++$i < 5 && $node !== null) {
6996
$node = $node->getAttribute('parentNode');
7097
}
71-
if ($node instanceof Node\Expr\FuncCall) {
72-
if ($def = $this->definitionResolver->resolveReferenceNodeToDefinition($node)) {
73-
$signature = new SignatureInformation;
74-
$signature->label = str_replace('()', '', $def->fqn) . '('.implode(', ', $def->parameters).')';
75-
$signature->documentation = $def->documentation;
76-
$signature->parameters = [];
77-
foreach ($def->parameters as $param) {
78-
$p = new ParameterInformation;
79-
$p->label = $param;
80-
$signature->parameters[] = $p;
81-
}
82-
$help->signatures[] = $signature;
83-
}
84-
} else if ($node instanceof Node\Name\FullyQualified || $node === null) {
85-
if (preg_match('([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$)', $line, $method)) {
86-
$fqn = $method[0] . '()';
87-
if ($def = $this->index->getDefinition($fqn)) {
88-
$signature = new SignatureInformation;
89-
$signature->label = $method[0] . '('.implode(', ', $def->parameters).')';
90-
$signature->documentation = $def->documentation;
91-
$signature->parameters = [];
92-
foreach ($def->parameters as $param) {
93-
$p = new ParameterInformation;
94-
$p->label = $param;
95-
$signature->parameters[] = $p;
96-
}
97-
$help->signatures[] = $signature;
98-
}
99-
}
100-
} else if ($node instanceof Node\Expr\MethodCall) {
101-
if ($def = $this->definitionResolver->resolveReferenceNodeToDefinition($node)) {
102-
$signature = new SignatureInformation;
103-
$signature->label = str_replace('()', '', explode('->', $def->fqn)[1]) . '('.implode(', ', $def->parameters).')';
104-
$signature->documentation = $def->documentation;
105-
$signature->parameters = [];
106-
foreach ($def->parameters as $param) {
107-
$p = new ParameterInformation;
108-
$p->label = $param;
109-
$signature->parameters[] = $p;
110-
}
111-
$help->signatures[] = $signature;
112-
}
113-
} else if ($node instanceof Node\Expr\PropertyFetch) {
98+
$params = '';
99+
if ($node instanceof Node\Expr\PropertyFetch) {
100+
fseek($handle, $node->name->getAttribute('startFilePos'));
101+
$method = fread($handle, ($node->name->getAttribute('endFilePos') + 1) - $node->name->getAttribute('startFilePos'));
102+
fseek($handle, $node->name->getAttribute('endFilePos') + 1);
103+
$params = fread($handle, ($filePos - 1) - $node->name->getAttribute('endFilePos'));
114104
if ($def = $this->definitionResolver->resolveReferenceNodeToDefinition($node->var)) {
115105
$fqn = $def->fqn;
116106
if (!$fqn) {
@@ -121,55 +111,65 @@ public function provideSignature(PhpDocument $doc, Position $pos): SignatureHelp
121111
$fqn = $fqns[0];
122112
}
123113
}
124-
$method = trim(substr($line, strrpos($line, ">") + 1));
125-
if ($method && $fqn) {
114+
if ($fqn) {
126115
$fqn = $fqn . '->' . $method . '()';
127-
if ($def = $this->index->getDefinition($fqn)) {
128-
$signature = new SignatureInformation;
129-
$signature->label = str_replace('()', '', explode('->', $def->fqn)[1]) . '('.implode(', ', $def->parameters).')';
130-
$signature->documentation = $def->documentation;
131-
$signature->parameters = [];
132-
foreach ($def->parameters as $param) {
133-
$p = new ParameterInformation;
134-
$p->label = $param;
135-
$signature->parameters[] = $p;
136-
}
137-
$help->signatures[] = $signature;
138-
}
116+
$def = $this->index->getDefinition($fqn);
139117
}
140118
}
119+
} else if ($node instanceof Node\Expr\MethodCall) {
120+
fseek($handle, $node->getAttribute('startFilePos'));
121+
$params = explode('(', fread($handle, $filePos - $node->getAttribute('startFilePos')), 2)[1];
122+
$def = $this->definitionResolver->resolveReferenceNodeToDefinition($node);
123+
} else if ($node instanceof Node\Expr\FuncCall) {
124+
fseek($handle, $node->getAttribute('startFilePos'));
125+
$params = explode('(', fread($handle, $filePos - $node->getAttribute('startFilePos')), 2)[1];
126+
$fqn = $this->definitionResolver->resolveReferenceNodeToFqn($node->name);
127+
$def = $this->index->getDefinition($fqn);
141128
} else if ($node instanceof Node\Expr\StaticCall) {
142-
if ($def = $this->definitionResolver->resolveReferenceNodeToDefinition($node)) {
143-
$signature = new SignatureInformation;
144-
$signature->label = str_replace('()', '', explode('::', $def->fqn)[1]) . '('.implode(', ', $def->parameters).')';
145-
$signature->documentation = $def->documentation;
146-
$signature->parameters = [];
147-
foreach ($def->parameters as $param) {
148-
$p = new ParameterInformation;
149-
$p->label = $param;
150-
$signature->parameters[] = $p;
151-
}
152-
$help->signatures[] = $signature;
153-
}
129+
fseek($handle, $node->getAttribute('startFilePos'));
130+
$params = explode('(', fread($handle, $filePos - $node->getAttribute('startFilePos')), 2)[1];
131+
$def = $this->definitionResolver->resolveReferenceNodeToDefinition($node);
154132
} else if ($node instanceof Node\Expr\ClassConstFetch) {
155-
if ($def = $this->definitionResolver->resolveReferenceNodeToDefinition($node->class)) {
156-
$method = trim(substr($line, strrpos($line, ":") + 1));
157-
if ($method) {
158-
$fqn = $def->fqn . '::' . $method . '()';
159-
if ($def = $this->index->getDefinition($fqn)) {
160-
$signature = new SignatureInformation;
161-
$signature->label = str_replace('()', '', explode('::', $def->fqn)[1]) . '('.implode(', ', $def->parameters).')';
162-
$signature->documentation = $def->documentation;
163-
$signature->parameters = [];
164-
foreach ($def->parameters as $param) {
165-
$p = new ParameterInformation;
166-
$p->label = $param;
167-
$signature->parameters[] = $p;
168-
}
169-
$help->signatures[] = $signature;
170-
}
133+
fseek($handle, $node->name->getAttribute('endFilePos') + 2);
134+
$params = fread($handle, ($filePos - 1) - $node->name->getAttribute('endFilePos'));
135+
fseek($handle, $node->name->getAttribute('startFilePos'));
136+
$method = fread($handle, ($node->name->getAttribute('endFilePos') + 1) - $node->name->getAttribute('startFilePos'));
137+
$method = explode('::', str_replace('()', '', $method), 2);
138+
$method = $method[1] ?? $method[0];
139+
$fqn = $this->definitionResolver->resolveReferenceNodeToFqn($node->class);
140+
$def = $this->index->getDefinition($fqn.'::'.$method.'()');
141+
} else {
142+
if (!preg_match('(([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*\((.*)$)', $line, $method)) {
143+
fclose($handle);
144+
return $help;
145+
}
146+
$def = $this->index->getDefinition($method[1] . '()');
147+
$params = $method[2];
148+
}
149+
fclose($handle);
150+
151+
if ($def) {
152+
$method = preg_split('(::|->)', str_replace('()', '', $def->fqn), 2);
153+
$method = $method[1] ?? $method[0];
154+
$signature = new SignatureInformation;
155+
$signature->label = $method . '('.implode(', ', $def->parameters).')';
156+
$signature->documentation = $def->documentation;
157+
$signature->parameters = [];
158+
foreach ($def->parameters as $param) {
159+
$p = new ParameterInformation;
160+
$p->label = $param;
161+
$signature->parameters[] = $p;
162+
}
163+
$help->activeSignature = 0;
164+
$help->activeParameter = 0;
165+
if (strlen(trim($params))) {
166+
try {
167+
$params = $this->parser->parse('<?php $a = [' . $params . '];', $this->parserErrorHandler)[0]->expr->items;
168+
$help->activeParameter = count($params);
169+
} catch (\Exception $e) {
171170
}
172171
}
172+
$help->signatures[] = $signature;
173173
}
174174

175175
return $help;

0 commit comments

Comments
 (0)