Skip to content

Commit

Permalink
ending-locations: Fix bug for ClassDefs with no decorators
Browse files Browse the repository at this point in the history
  • Loading branch information
david-yz-liu committed Dec 9, 2021
1 parent fee49b4 commit ed569da
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
2. False negative when the loop variable can be simplified, but is also shadowed in the
the loop body.
- Fix HTML report to link correctly to specific errors on the PythonTA documentation website.
- Fix bug when setting ending locations for `ClassDef`s that have no decorators.

### New checkers

Expand Down
5 changes: 5 additions & 0 deletions examples/ending_locations/class_def.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
@wrapper
class Foo(base1, base2):
pass


class Bar:
def __init__(self):
pass
8 changes: 8 additions & 0 deletions examples/ending_locations/function_def.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,11 @@ def fun(arg) -> str:
"""
return_annotation = "cool!"
return return_annotation


def fun2(arg) -> str:
"""
This is a function fun2.
"""
return_annotation = "cool!"
return return_annotation
13 changes: 11 additions & 2 deletions python_ta/transforms/setendings.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ def init_register_ending_setters(source_code):

# Ad hoc transformations
ending_transformer.register_transform(nodes.BinOp, _set_start_from_first_child)
ending_transformer.register_transform(nodes.ClassDef, _set_start_from_first_child)
ending_transformer.register_transform(nodes.FunctionDef, _set_start_from_first_child)
ending_transformer.register_transform(nodes.ClassDef, _set_start_from_first_decorator)
ending_transformer.register_transform(nodes.FunctionDef, _set_start_from_first_decorator)
ending_transformer.register_transform(nodes.Tuple, _set_start_from_first_child)
ending_transformer.register_transform(nodes.Arguments, fix_arguments(source_code))
ending_transformer.register_transform(nodes.Slice, fix_slice(source_code))
Expand Down Expand Up @@ -406,6 +406,15 @@ def _set_start_from_first_child(node):
return node


def _set_start_from_first_decorator(node):
"""Set the start attributes of this node from its first child, if that child is a decorator."""
if getattr(node, "decorators"):
first_child = node.decorators
node.fromlineno = first_child.fromlineno
node.col_offset = first_child.col_offset
return node


def set_from_last_child(node):
"""Populate ending locations for astroid node based on its last child.
Expand Down
6 changes: 3 additions & 3 deletions tests/test_setendings.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def test_call(self):
self.set_and_check(module, nodes.Call, expected)

def test_classdef(self):
expected = [(1, 3, 0, 8)]
expected = [(1, 3, 0, 8), (6, 8, 0, 12)]
module = self.get_file_as_module("class_def.py")
self.set_and_check(module, nodes.ClassDef, expected)

Expand Down Expand Up @@ -257,8 +257,8 @@ def test_for(self):
self.set_and_check(module, nodes.For, expected)

def test_functiondef(self):
"""Note: this node includes the decorator."""
expected = [(1, 7, 0, 28)]
"""Note: this node includes the decorator, if applicable."""
expected = [(1, 7, 0, 28), (10, 15, 0, 28)]
module = self.get_file_as_module("function_def.py")
self.set_and_check(module, nodes.FunctionDef, expected)

Expand Down

0 comments on commit ed569da

Please sign in to comment.