Skip to content

Commit

Permalink
Support lint ignore directives in more places
Browse files Browse the repository at this point in the history
Adds logic to `LintRule.node_comments()` looking for directives in more
locations relative to the current node:

- trailing inline comments after commas
- preceding and trailing comments inside brackets
- preceding comments before/after decorators for classes and functions

In addition, to better support suppressions for decorators themselves,
the logic to break upward searching until reaching a `leading_lines`
node has been modified to exclude `Decorator` nodes which have their own
leading lines that aren't used for the first decorator on a class.

Based on code examples reported in #413

ghstack-source-id: 4907870d9ecde15fd1110b3d276bc7f95569c513
Pull Request resolved: #441
  • Loading branch information
amyreese committed Apr 20, 2024
1 parent 130cc41 commit a052284
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 4 deletions.
38 changes: 35 additions & 3 deletions src/fixit/rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@
from libcst import (
BaseSuite,
BatchableCSTVisitor,
Comma,
CSTNode,
Decorator,
EmptyLine,
IndentedBlock,
LeftSquareBracket,
Module,
RightSquareBracket,
SimpleStatementSuite,
TrailingWhitespace,
)
Expand Down Expand Up @@ -134,14 +138,42 @@ def node_comments(self, node: CSTNode) -> Generator[str, None, None]:
if tw and tw.comment:
yield tw.comment.value

comma: Optional[Comma] = getattr(node, "comma", None)
if isinstance(comma, Comma):
tw = getattr(comma.whitespace_after, "first_line", None)
if tw and tw.comment:
yield tw.comment.value

rb: Optional[RightSquareBracket] = getattr(node, "rbracket", None)
if rb is not None:
tw = getattr(rb.whitespace_before, "first_line", None)
if tw and tw.comment:
yield tw.comment.value

el: Optional[Sequence[EmptyLine]] = None
lb: Optional[LeftSquareBracket] = getattr(node, "lbracket", None)
if lb is not None:
el = getattr(lb.whitespace_after, "empty_lines", None)
if el is not None:
for line in el:
if line.comment:
yield line.comment.value

el = getattr(node, "lines_after_decorators", None)
if el is not None:
for line in el:
if line.comment:
yield line.comment.value

ll: Optional[Sequence[EmptyLine]] = getattr(node, "leading_lines", None)
if ll is not None:
for line in ll:
if line.comment:
yield line.comment.value
# stop looking once we've gone up far enough for leading_lines,
# even if there are no comment lines here at all
break
if not isinstance(node, Decorator):
# stop looking once we've gone up far enough for leading_lines,
# even if there are no comment lines here at all
break

node = self.get_metadata(ParentNodeProvider, node)

Expand Down
2 changes: 1 addition & 1 deletion src/fixit/tests/rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ class Foo(object):
):
idx += 1
content = dedent(code).encode("utf-8")
with self.subTest(f"test case {idx}"):
with self.subTest(f"test ignore {idx}"):
runner = LintRunner(Path("fake.py"), content)
violations = list(
runner.collect_violations([ExerciseReportRule()], Config())
Expand Down

0 comments on commit a052284

Please sign in to comment.