davidhalter / jedi

Awesome autocompletion, static analysis and refactoring library for python
http://jedi.readthedocs.io
Other
5.83k stars 507 forks source link

TypedDict argument autocompletion #1740

Open RobertCraigie opened 3 years ago

RobertCraigie commented 3 years ago

For example

class Metadata(TypedDict):
    created_at: datetime.datetime

class Data(TypedDict):
    title: str
    published: bool
    metadata: Metadata

def foo(data: Data):
   ...

foo({' -> ['title', 'published', 'metadata'] foo({'t -> ['title'] foo({'metadata': {' -> ['created_at']

I did see the comment on #1700

The hard part here is not the completion part, it's that you have to infer the type that is needed at a specific position, which is not something Jedi can do, at the moment.

I would be happy to put some work into that, however I am not very familiar with the jedi internals, so if you have any pointers it would be much appreciated, thanks

davidhalter commented 3 years ago

I would be happy to put some work into that, however I am not very familiar with the jedi internals, so if you have any pointers it would be much appreciated, thanks

If you want to work on this playing with api/strings.py is going to be a good starter. However the hard part is the type inference part. It's definitely easier than #1700, but it's probably still a few days of work (at least).

However I'm only going to merge this if there are no hacks/heuristics in there.

RobertCraigie commented 3 years ago

I underestimated the amount of work it would take on my end to get this feature implemented and don't really have the time to work on this given my current workload.

I've sponsored you and it would be much appreciated if you could try and get this feature implemented as soon as possible, thanks.

davidhalter commented 3 years ago

Hey, thanks a lot for sponsoring the project. I'm definitely in favor of eventually implementing this, but I'm not sure it will happen very soon and I cannot promise you that this will ever happen.

There is simply a lot of prior work that's missing and the parser is also not helping a lot. As I said, I estimate this at like 2 days of full time work for me, which is a lot :/ So I hope I eventually get around to implement this, but I cannot promise.

davidhalter commented 3 years ago

If you have full control over the code base, you could use dataclasses instead of TypedDict. It's probably pretty easy to transform from and to dicts.

RobertCraigie commented 3 years ago

I cannot promise you that this will ever happen.

No worries, I will have time to work on this myself eventually but I did struggle with figuring out how I would go about inferring the argument types. I found it easy to find the current argument but was lost with what to do after that so any extra guidance would be greatly appreciated, thanks.

you could use dataclasses instead of TypedDict

I do have full control over the code base however as it is a public facing api I wanted to avoid requiring a massive amount of imports as the arguments can be nested deeply. There are other ways I can implement the api but in my opinion none are as clean or easy to use as plain dictionaries would be with autocomplete support.

davidhalter commented 3 years ago

Inferring the argument types is probably not that hard (not 100% sure though). I initially thought that it would be hard, but it's probably not. You can probably just use self._signatures_callback in api/completion.py and get the output of the documented def get_signatures(). From there you can access the different parameters and even which parameter it is. The hard part is probably working out all the error cases with the parser.