Filter out language-keyword completions in places where only an expression can be valid syntax
For example, in this situation, raise should not be included as a completion suggestion, because for x in raise is invalid syntax (Python's grammar dictates that only an expression can follow the sequence for <EXPR> in ):
Similarly, it's a bit annoying that finally is at the top of the list here when syntactically it would only ever be invalid syntax for a keyword to appear in this position:
https://github.com/astral-sh/ruff/pull/21979 did this for for ... in <CURSOR>.
I wonder if it make senses to approach this issue more methodically. That is, enumerate all classes of "must be an expression" locations, and then try to convert that to code so that we can more holistically rule out things that aren't expressions (or can't become expressions).
Otherwise it seems likely this will just be a whack-a-mole kind of thing.
enumerate all classes of "must be an expression" locations
Why not just use the formal Python grammar for this, then you can avoid suggesting something that leads to invalid syntax in all cases? Should also make it easy to support different Python versions (maintaining https://github.com/astral-sh/ruff/pull/22002 as the grammar grows is going to lead to a lot of conditionals, I imagine).
@gablank Can you elaborate? What specifically are you suggesting?
I am making quite a few assumptions on how ty works here, but reading https://github.com/astral-sh/ruff/pull/22002 it seems to me like what ty lists as valid next keywords is just based on "hardcoding", i.e. "if the current state is for x in <iter>:<CURSOR>, then yield, return, await etc. are valid keywords".
What I'm asking is why the grammar itself isn't used to generate up all this, instead of encoding that logic by hand?
I guess you're kind of suggesting the same in this comment, although maybe a special case of what I'm asking about?
I wonder if it make senses to approach this issue more methodically. That is, enumerate all classes of "must be an expression" locations, and then try to convert that to code so that we can more holistically rule out things that aren't expressions (or can't become expressions).
What I'm asking is why the grammar itself isn't used to generate up all this, instead of encoding that logic by hand?
generating some kind of schema from the formal grammar at https://github.com/python/cpython/blob/3.14/Grammar/python.gram is an interesting idea. It sounds hard, though
I believe this should now be closed by https://github.com/astral-sh/ruff/pull/22002