1
0
Fork 0

added param count

pull/250/head
Ivan Bozhanov 2017-01-20 15:26:14 +02:00
parent 16c7560993
commit 3b4e0c3275
5 changed files with 114 additions and 106 deletions

View File

@ -3,4 +3,5 @@
function helpFunc1(int $count = 0) function helpFunc1(int $count = 0)
{ {
} }
helpFunc1() helpFunc1()

View File

@ -3,4 +3,7 @@
function helpFunc2(int $count = 0) function helpFunc2(int $count = 0)
{ {
} }
$a = 1;
helpFunc2( helpFunc2(

View File

@ -7,9 +7,11 @@ class HelpClass2
} }
public function test() public function test()
{ {
$this->method( $this->method(1,1);
} }
} }
$a = new HelpClass2; $a = new HelpClass2;
$a->method(1, $a
->method(
1,
array(),

View File

@ -7,4 +7,6 @@ class HelpClass4
} }
} }
HelpClass4::method( HelpClass4::method(1, 2, 3
HelpClass4::method(1, 2, 3

View File

@ -3,9 +3,11 @@ declare(strict_types = 1);
namespace LanguageServer; namespace LanguageServer;
use PhpParser\ErrorHandler\Collecting;
use PhpParser\Node; use PhpParser\Node;
use LanguageServer\Index\ReadableIndex; use LanguageServer\Index\ReadableIndex;
use LanguageServer\Protocol\{ use LanguageServer\Protocol\{
Range,
Position, Position,
SignatureHelp, SignatureHelp,
SignatureInformation, SignatureInformation,
@ -24,6 +26,16 @@ class SignatureHelpProvider
*/ */
private $index; private $index;
/**
* @var Parser
*/
private $parser;
/**
* @var Parser
*/
private $parserErrorHandler;
/** /**
* @param DefinitionResolver $definitionResolver * @param DefinitionResolver $definitionResolver
* @param ReadableIndex $index * @param ReadableIndex $index
@ -32,6 +44,8 @@ class SignatureHelpProvider
{ {
$this->definitionResolver = $definitionResolver; $this->definitionResolver = $definitionResolver;
$this->index = $index; $this->index = $index;
$this->parser = new Parser;
$this->parserErrorHandler = new Collecting;
} }
/** /**
@ -46,71 +60,47 @@ class SignatureHelpProvider
$help = new SignatureHelp; $help = new SignatureHelp;
$help->signatures = []; $help->signatures = [];
$newPos = clone $pos; $handle = fopen($doc->getUri(), 'r');
$line = explode("\n", $doc->getContent())[$newPos->line]; $lines = [];
do { for ($i = 0; $i < $pos->line; $i++) {
$newPos->character --; $lines[] = strlen(fgets($handle));
} while ($newPos->character > 0 && $line[$newPos->character] !== "("); }
$filePos = ftell($handle) + $pos->character;
$line = substr(fgets($handle), 0, $pos->character);
fseek($handle, 0);
if (!$newPos->character) { do {
$node = $doc->getNodeAtPosition($pos);
$pos->character--;
if ($pos->character < 0) {
$pos->line --;
if ($pos->line < 0) {
break;
}
$pos->character = $lines[$pos->line];
}
} while ($node === null);
if ($node === null) {
fclose($handle);
return $help; return $help;
} }
$line = substr($line, 0, $newPos->character); $i = 0;
while (!(
$newPos->character --; $node instanceof Node\Expr\PropertyFetch ||
$node instanceof Node\Expr\MethodCall ||
$node = $doc->getNodeAtPosition($newPos); $node instanceof Node\Expr\FuncCall ||
$node instanceof Node\Expr\ClassConstFetch ||
if ($node instanceof Node\Expr\Error) { $node instanceof Node\Expr\StaticCall
) && ++$i < 5 && $node !== null) {
$node = $node->getAttribute('parentNode'); $node = $node->getAttribute('parentNode');
} }
$params = '';
if ($node instanceof Node\Expr\Error) { if ($node instanceof Node\Expr\PropertyFetch) {
$node = $node->getAttribute('parentNode'); fseek($handle, $node->name->getAttribute('startFilePos'));
} $method = fread($handle, ($node->name->getAttribute('endFilePos') + 1) - $node->name->getAttribute('startFilePos'));
if ($node instanceof Node\Expr\FuncCall) { fseek($handle, $node->name->getAttribute('endFilePos') + 1);
if ($def = $this->definitionResolver->resolveReferenceNodeToDefinition($node)) { $params = fread($handle, ($filePos - 1) - $node->name->getAttribute('endFilePos'));
$signature = new SignatureInformation;
$signature->label = str_replace('()', '', $def->fqn) . '('.implode(', ', $def->parameters).')';
$signature->documentation = $def->documentation;
$signature->parameters = [];
foreach ($def->parameters as $param) {
$p = new ParameterInformation;
$p->label = $param;
$signature->parameters[] = $p;
}
$help->signatures[] = $signature;
}
} else if ($node instanceof Node\Name\FullyQualified || $node === null) {
if (preg_match('([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$)', $line, $method)) {
$fqn = $method[0] . '()';
if ($def = $this->index->getDefinition($fqn)) {
$signature = new SignatureInformation;
$signature->label = $method[0] . '('.implode(', ', $def->parameters).')';
$signature->documentation = $def->documentation;
$signature->parameters = [];
foreach ($def->parameters as $param) {
$p = new ParameterInformation;
$p->label = $param;
$signature->parameters[] = $p;
}
$help->signatures[] = $signature;
}
}
} else if ($node instanceof Node\Expr\MethodCall) {
if ($def = $this->definitionResolver->resolveReferenceNodeToDefinition($node)) {
$signature = new SignatureInformation;
$signature->label = str_replace('()', '', explode('->', $def->fqn)[1]) . '('.implode(', ', $def->parameters).')';
$signature->documentation = $def->documentation;
$signature->parameters = [];
foreach ($def->parameters as $param) {
$p = new ParameterInformation;
$p->label = $param;
$signature->parameters[] = $p;
}
$help->signatures[] = $signature;
}
} else if ($node instanceof Node\Expr\PropertyFetch) {
if ($def = $this->definitionResolver->resolveReferenceNodeToDefinition($node->var)) { if ($def = $this->definitionResolver->resolveReferenceNodeToDefinition($node->var)) {
$fqn = $def->fqn; $fqn = $def->fqn;
if (!$fqn) { if (!$fqn) {
@ -121,44 +111,48 @@ class SignatureHelpProvider
$fqn = $fqns[0]; $fqn = $fqns[0];
} }
} }
$method = trim(substr($line, strrpos($line, ">") + 1)); if ($fqn) {
if ($method && $fqn) {
$fqn = $fqn . '->' . $method . '()'; $fqn = $fqn . '->' . $method . '()';
if ($def = $this->index->getDefinition($fqn)) { $def = $this->index->getDefinition($fqn);
$signature = new SignatureInformation;
$signature->label = str_replace('()', '', explode('->', $def->fqn)[1]) . '('.implode(', ', $def->parameters).')';
$signature->documentation = $def->documentation;
$signature->parameters = [];
foreach ($def->parameters as $param) {
$p = new ParameterInformation;
$p->label = $param;
$signature->parameters[] = $p;
}
$help->signatures[] = $signature;
}
} }
} }
} else if ($node instanceof Node\Expr\MethodCall) {
fseek($handle, $node->getAttribute('startFilePos'));
$params = explode('(', fread($handle, $filePos - $node->getAttribute('startFilePos')), 2)[1];
$def = $this->definitionResolver->resolveReferenceNodeToDefinition($node);
} else if ($node instanceof Node\Expr\FuncCall) {
fseek($handle, $node->getAttribute('startFilePos'));
$params = explode('(', fread($handle, $filePos - $node->getAttribute('startFilePos')), 2)[1];
$fqn = $this->definitionResolver->resolveReferenceNodeToFqn($node->name);
$def = $this->index->getDefinition($fqn);
} else if ($node instanceof Node\Expr\StaticCall) { } else if ($node instanceof Node\Expr\StaticCall) {
if ($def = $this->definitionResolver->resolveReferenceNodeToDefinition($node)) { fseek($handle, $node->getAttribute('startFilePos'));
$signature = new SignatureInformation; $params = explode('(', fread($handle, $filePos - $node->getAttribute('startFilePos')), 2)[1];
$signature->label = str_replace('()', '', explode('::', $def->fqn)[1]) . '('.implode(', ', $def->parameters).')'; $def = $this->definitionResolver->resolveReferenceNodeToDefinition($node);
$signature->documentation = $def->documentation;
$signature->parameters = [];
foreach ($def->parameters as $param) {
$p = new ParameterInformation;
$p->label = $param;
$signature->parameters[] = $p;
}
$help->signatures[] = $signature;
}
} else if ($node instanceof Node\Expr\ClassConstFetch) { } else if ($node instanceof Node\Expr\ClassConstFetch) {
if ($def = $this->definitionResolver->resolveReferenceNodeToDefinition($node->class)) { fseek($handle, $node->name->getAttribute('endFilePos') + 2);
$method = trim(substr($line, strrpos($line, ":") + 1)); $params = fread($handle, ($filePos - 1) - $node->name->getAttribute('endFilePos'));
if ($method) { fseek($handle, $node->name->getAttribute('startFilePos'));
$fqn = $def->fqn . '::' . $method . '()'; $method = fread($handle, ($node->name->getAttribute('endFilePos') + 1) - $node->name->getAttribute('startFilePos'));
if ($def = $this->index->getDefinition($fqn)) { $method = explode('::', str_replace('()', '', $method), 2);
$method = $method[1] ?? $method[0];
$fqn = $this->definitionResolver->resolveReferenceNodeToFqn($node->class);
$def = $this->index->getDefinition($fqn.'::'.$method.'()');
} else {
if (!preg_match('(([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*\((.*)$)', $line, $method)) {
fclose($handle);
return $help;
}
$def = $this->index->getDefinition($method[1] . '()');
$params = $method[2];
}
fclose($handle);
if ($def) {
$method = preg_split('(::|->)', str_replace('()', '', $def->fqn), 2);
$method = $method[1] ?? $method[0];
$signature = new SignatureInformation; $signature = new SignatureInformation;
$signature->label = str_replace('()', '', explode('::', $def->fqn)[1]) . '('.implode(', ', $def->parameters).')'; $signature->label = $method . '('.implode(', ', $def->parameters).')';
$signature->documentation = $def->documentation; $signature->documentation = $def->documentation;
$signature->parameters = []; $signature->parameters = [];
foreach ($def->parameters as $param) { foreach ($def->parameters as $param) {
@ -166,11 +160,17 @@ class SignatureHelpProvider
$p->label = $param; $p->label = $param;
$signature->parameters[] = $p; $signature->parameters[] = $p;
} }
$help->activeSignature = 0;
$help->activeParameter = 0;
if (strlen(trim($params))) {
try {
$params = $this->parser->parse('<?php $a = [' . $params . '];', $this->parserErrorHandler)[0]->expr->items;
$help->activeParameter = count($params);
} catch (\Exception $e) {
}
}
$help->signatures[] = $signature; $help->signatures[] = $signature;
} }
}
}
}
return $help; return $help;
} }