-
-
Notifications
You must be signed in to change notification settings - Fork 290
Create AssignName
nodes for ClassDef
and FunctionDef
#1390
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
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 like this idea a lot. Smart use of tokenize
.
Perhaps some pre-mature comments, but thought I would make them while I was looking anyway.
Two additional comments:
- With respect to
pylint
, I indeed think anisintance
check onadd_message
makes the most sense. This make sure we never forget to passname_node
when we're dealing with these types of nodes, which is likely to happen down the line. Performance impact should be negligible. - I'm wondering if we should include everything until the
:
in thisname_node
? Technically, that is all part of the assignment right? And we might need access to the arguments or typing included down the line. Perhaps we should create anAssign
node for the complete assignment and thenclass ClassName
asAssignName
within that? Or that might be overcomplicating too much.
self, | ||
manager: AstroidManager, | ||
parser_module: Optional[ParserModule] = None, | ||
data: Optional[str] = None, |
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.
According to the typing you added in astroid/builder.py
this should be str
right? I don't see any other place where TreeRebuilder
is instantiated.
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.
True, inside astroid
it will always be str
. Technically, you could consider TreeRebuilder
part of the public interface however. Adding a new required argument would then be a breaking change.
Defining it as Optional
isn't too bad considering everything. The name_node
/ position
needs to be Optional
, so a small check if not self._data
doesn't really hurt.
if not self._data: | ||
return None | ||
end_lineno: Optional[int] = getattr(node, "end_lineno", None) | ||
if node.body: |
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 will need to see how this interacts with docstrings
etc. Those are part of the body
in ast
but not in astroid
. You probably thought about this 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.
node
here is the ast
one. So that should work. AFAIK each function / class body needs at least one node to be valid Python (either a docstring, pass, or something else). In any case if body
should somehow be empty, it would fallback to the end_lineno
of the node itself. Or if that also didn't work None
, which is essentially self._data[node.lineno - 1 : ]
.
search_token_name = "def" | ||
else: | ||
search_token_name = "class" | ||
token_found: bool = False |
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 bool
necessary here?
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.
Not necessary, I find it helpful never the less :)
I think it's better to highlight The missing docstring example is illustrating that well : Highlighting the whole class make the most sense but is too disruptive, highlighting another part of the class makes you think there is a problem in this part, but highlighting the real problem is impossible as it's something that is missing in the class. So imo highlighting a zero length warning at the beggining of the node is the right compromise (for message that are a full line long or more). Also I think defining the boundary of the warnings is a decision to make in pylint and not in astroid. Astroid should permit to recover line and column boundary of the node (and of element inside the node) , then add_message display nodes the way it see fits. |
Agreed. Although we could probably add an option to We could also think about if it would make sense adding that position attribute to the Node base class. Although initially only
I don't think that makes sense. The arguments are already included in other child nodes and
Although zero length ranges / positions work, they aren't ideal for highlighting. At least VS Code chooses to only highlight a single char in that case. Let's try including the
That would be the case either way. The issue at the moment is that pylint doesn't have access to the exact keyword - name position / range. That's what this PR would solve. |
Closing it in favor of #1393 to preserve the idea and discussion here. |
Please note that the comment I was talking about is already highly up-voted for a 5 days old comment. It says:
I asked kovla what he thinks about the proposition, let's see. |
Description
A first attempt to add better position information for names in
ClassDef
andFunctionDef
.Could be used to resolve: pylint-dev/pylint#5466
At the moment, this is only a proof of concept!
During my last comments I suggested replacing the
name
attribute with a dedicated (AssignName
) node. This would be a large breaking change. @DanielNoord Helped convince me that backwards compatible solutions would be better and much easier to implement in pylint. So instead of changing an existing attribute, I've added a new onename_node
.To get the actual position within the source code, I've used the
tokenize
module. The code itself works already. The required change in pylint would be to replace theClassDef
andFunctionDef
nodes in error messages with the newname_node
.An example how it will look, here with the
missing-docstring
error.While looking at that, I was wondering if it would be better to highlight a bit more, i.e. include
class
/def
? After all, in general those are errors on the class / function and not the name itself. The parsing is already in place, so it would be quite easy to modify.If we decide to that, it's probably better to store the position information inside an attribute instead of a dedicated node.
We could also think about the implementation in
pylint
again. My initial idea to replace all nodes inadd_message
calls might not be the best way to do things after all. I think @DanielNoord suggested it (maybe in a different context), we could probably modify theadd_message
function itself to use the new position attribute forClassDef
andFunctionDef
nodes./CC: @Pierre-Sassoulas @DanielNoord
Edit
The alternative:
Type of Changes