-
Notifications
You must be signed in to change notification settings - Fork 213
Allow Jedi "goto" to perform multiple hops for "go to definition" #443
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
pylsp/plugins/definition.py
Outdated
def _resolve_definition( | ||
maybe_defn: Name, script: Script, settings: Dict[str, Any] | ||
) -> Name: | ||
while not maybe_defn.is_definition() and maybe_defn.module_path == script.path: |
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.
Is there a guarantee that this will never become an infinite loop, for example if follow_imports
is True and the two modules (wrongly) import the same symbol from each other? If not, is it worth adding a limit of how many iterations can be performed, setting it to something arbitrarily large and raising an informative exception if it is exceeded?
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.
Right now this doesn't follow hops across modules (that should be fixed as a followup potentially), but generally I agree it would be good to be robust to jedi or other weird user-introduced circular references. Added what feels like a reasonable limit to me (100 hops) but happy to adjust if there's another good reason to do so.
@krassowski, this looks good to me now. Are you ok with merging? |
Yes. My only suggestion would be adding another test based on the code snippet in https://jedi.readthedocs.io/en/latest/docs/api.html#type-inference-goto to show that this still works as expected. |
Also, was there ever a discussion upstream on why this is preferred behaviour in jedi? |
Not to my knowledge. @davidhalter, we'd appreciate your input here if you have some free time. |
This should probably be changed upstream, yes. I feel like this implementation has almost no upsides and a lot of downsides when it comes to potential caching issues or recursive stuff (it's probably also considerably slower). |
Depending on the application, I can see the value of a I unfortunately won't have cycles for a little while to implement anything on the jedi side if the consensus is to change this upstream. If other folks are similarly lacking cycles, maybe we could add something in pylsp that does the following:
That way, whenever somebody does have cycles to submit a PR to jedi implementing this suggestion (assuming it makes sense of course), it will get automatically picked up by pylsp. ^ What do folks think about that? |
Yeah, I think we don't have time for that.
Until this is fixed in Jedi, I think there's no need to implement the first part and only go with the second one (which is what you've already done). @krassowski, what do you think? |
Yes, we are version pinning jedi in python-lsp-server anyways so it makes sense to keep it as-is. Let's just add the test case I mentioned earlier, open an issue to track the future planned improvement (whether on jedi side or in here) and then I think we can merge this patch in. |
Done! (My assumption is that we do not want the multihop behavior in this case, since the 1-hop goto is still an actual definition)
I will do it here: #446 |
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 looks good to me, just one comment to update.
The implementation of lsp definitions performs one hop of jedi "goto". This is inadequate for cases such as the following:
A "definitions" request on the final reference to
d
will run a jedi goto that finds the reference to d ind[0] = 0
, which then gets filtered out by the language server because it's not considered a definition. To fix, when we run agoto
that finds something that's not a definition, keep runninggoto
s on the thing we found until we either do find one, or exhaust the chain.Added a unit test to cover this case, as well as type definitions to the definitions plugin.