-
Notifications
You must be signed in to change notification settings - Fork 185
Go to definition support #49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
* constants * static properties * static methods
Current coverage is 89.67% (diff: 88.88%)@@ master #49 diff @@
==========================================
Files 19 21 +2
Lines 291 455 +164
Methods 45 66 +21
Messages 0 0
Branches 0 0
==========================================
+ Hits 267 408 +141
- Misses 24 47 +23
Partials 0 0
|
2959b05
to
9f2d3a4
Compare
Anyone have an idea what kind of sorcery this is? $project = $this->project;
How can this error ever happen when reading from |
{ | ||
if ( | ||
!isset($this->node) | ||
&& $node->getAttribute('startLine') <= $this->position->line + 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will not work, you are assuming the node spans a rectangular section of the source code.
First and last line have to be handled separately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be fixed now, could you take a look?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good to me
That's a lot of changes... can you give a summary when you are finished? |
@madhed All the latest commits were pretty much bug fixes. I tried to make the commits easy to review one-by-one (actually spend quite some time rebasing). Test refactoring etc. should be self-explanatory. 4786fe1, befb07d: This adds new attributes to each Node that allow you to get the parent node, siblings and the document of the node. Inspired by Implementation of definition request (5fc35e7): To get the definition, we first have to find the node under the cursor. This is done by the Once we have the node we want to get the definition for, we build the FQN from it. Finally, I removed the |
a0ad0ef
to
6309b73
Compare
Squashed some commits to ease reviewing. |
Ok let me check this out. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall good, but a fatal error must be fixed. More rigorous testing is advised.
Furthermore I was not able to goto definition of parameter type hints. Is this expected?
Memory consumption went up to 264MiB but this was to be expected.
{ | ||
if ($node instanceof Node\Stmt\ClassLike && isset($node->name)) { | ||
// Class, interface or trait declaration | ||
$this->definitions[(string)$node->namespacedName] = $node; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the existance of name
implies that namespacedName
is also set, but maybe check for isset($node->namespaceName)
to avoid confusion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I read isset($node->name)
as does the class have a name? e.g. is the class an anonymous class? which is why I wrote it like this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough, it just looked like a bug at first because you test for one attribute but access another.
return null; | ||
} | ||
// Need to resolve variable to a class | ||
$varDef = $this->getVariableDefinition($node->var); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This crashes with fatal when trying to goto definition of write
in $this->protocolWriter->write
.
Fatal error: Uncaught TypeError: Argument 1 passed to LanguageServer\PhpDocument::getVariableDefinition() must be an instance of PhpParser\Node\Expr\Variable, instance of PhpParser\Node\Expr\PropertyFetch given, called in E:\Projekte\php-language-server\src\PhpDocument.php on line 315 and defined in E:\Projekte\php-language-server\src\PhpDocument.php:391
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just fixed this and amended
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, fixed
Node\Const_::class => SymbolKind::CONSTANT | ||
]; | ||
$symbols = []; | ||
foreach ($this->definitions as $fqn => $node) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Warning: Invalid argument supplied for foreach
when invoking workspace/symbol
search
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you reproduce? Maybe this is only when parsing hasn't finished yet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can reproduce, let the indexer run all the way through. Every time(!) I open workspace symbol search the warning appears. The search works, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can reproduce too. But it is weird because parse()
sets it to an array and getSymbols()
never runs before parse()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just found it. It comes from invalid_file.php
. It's never successfully parsed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed it
6309b73
to
844707b
Compare
Works for the trivial cases, but feels a little brittle all around... what do you think? Also some time later we should switch to a custom AST representation like @mniewrzal proposed in #31 (comment) this would probably decrease the memory footprint a lot and also tidy up the code quite a bit. I was a sometimes bit lost while reviewing 😁 Also I just noticed when there are multiple assignment to a variable and you go to its definition, it just jumps up one assignment instead of going to the first one. |
Yeah well the type resolving is still not very good. That will play a bigger role for provideCompletion. I want to get basic support for the major requests asap
For sure.
Still not 100% sold on this. The AST nodes are very very powerful to work with. Recreating them all seems a bit pointless to me. But what we can do now is not keep the file content in memory anymore, because we only need it at parse time for errors and use the AST afterwards. That alone will reduce memory usage (the AST doesn't hold any content, only structure), but as I said already in other places I'm not concerned at the moment with RAM usage, rather with features and response times.
Yeah, noticed that later on too. The algorithms picks the closest definition. Instead, it should go all the way up to a function node and then down again to find the declaration. But that is much more complicated because you need to make sure you are going the right path. |
Fixed |
@@ -53,7 +53,7 @@ class PhpDocument | |||
* | |||
* @var Node[] | |||
*/ | |||
private $stmts; | |||
private $stmts = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is good - there is a semantic difference between "a document has no statements" and "we couldn't parse the statements"
Please avoid merge commits |
Keep AST in memory
Move logic to PhpDocument::getDefininedFqn() for reusability Fix DefinitionResolverTest
1fbff27
to
7f95b76
Compare
Closes #19
Works for
use
)use
statements that import a class-likeimplements
/extends
What does not work yet:
Classes, interfaces, traits, methods, properties and constant declarations get indexed by their fully qualified name at parse time.
Examples for FQNs:
TestNamespace\testFunction()
TestNamespace\TEST_CONSTANT
TestNamespace\TestClass
TestNamespace\TestClass::TEST_CONSTANT
TestNamespace\TestClass::staticTestProperty
TestNamespace\TestClass::testProperty
TestNamespace\TestClass::staticTestMethod()
TestNamespace\TestClass::testMethod()
At a definition request, the node under the cursor is searched for and the referenced FQN is constructed (except for variables). Then the index is searched for that FQN.
Variables are resolved at request by traversing the AST upwards from the node under the cursor.
Other changes: