Skip to content

Commit

Permalink
Bool expression comment placement (#7269)
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaReiser authored Sep 12, 2023
1 parent c21b960 commit 1e6df19
Show file tree
Hide file tree
Showing 12 changed files with 776 additions and 145 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,14 @@
(1 << (n + 2*n-1 + i+j)) # NE-SW ordinal
for j in rangen]

rowuses = [((1 << j) # column ordinal
)|
(
# comment
(1 << (n + i-j + n-1))) | # NW-SE ordinal
(1 << (n + 2*n-1 + i+j)) # NE-SW ordinal
for j in rangen]

skip_bytes = (
header.timecnt * 5 # Transition times and types
+ header.typecnt * 6 # Local time type records
Expand All @@ -328,3 +336,56 @@
+ header.isstdcnt # Standard/wall indicators
+ header.isutcnt # UT/local indicators
)


if (
(1 + 2) # test
or (3 + 4) # other
or (4 + 5) # more
):
pass


if (
(1 and 2) # test
+ (3 and 4) # other
+ (4 and 5) # more
):
pass


if (
(1 + 2) # test
< (3 + 4) # other
> (4 + 5) # more
):
pass

z = (
a
+
# a: extracts this comment
(
# b: and this comment
(
# c: formats it as part of the expression
x and y
)
)
)

z = (
(

(

x and y
# a: formats it as part of the expression

)
# b: extracts this comment

)
# c: and this comment
+ a
)
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,86 @@ def test():
and {k.lower(): v for k, v in self.items()}
== {k.lower(): v for k, v in other.items()}
)



if "_continue" in request.POST or (
# Redirecting after "Save as new".
"_saveasnew" in request.POST
and self.save_as_continue
and self.has_change_permission(request, obj)
):
pass


if True:
if False:
if True:
if (
self.validate_max
and self.total_form_count() - len(self.deleted_forms) > self.max_num
) or self.management_form.cleaned_data[
TOTAL_FORM_COUNT
] > self.absolute_max:
pass


if True:
if (
reference_field_name is None
or
# Unspecified to_field(s).
to_fields is None
or
# Reference to primary key.
(
None in to_fields
and (reference_field is None or reference_field.primary_key)
)
or
# Reference to field.
reference_field_name in to_fields
):
pass


field = opts.get_field(name)
if (
field.is_relation
and
# Generic foreign keys OR reverse relations
((field.many_to_one and not field.related_model) or field.one_to_many)
):
pass


if True:
return (
filtered.exists()
and
# It may happen that the object is deleted from the DB right after
# this check, causing the subsequent UPDATE to return zero matching
# rows. The same result can occur in some rare cases when the
# database returns zero despite the UPDATE being executed
# successfully (a row is matched and updated). In order to
# distinguish these two cases, the object's existence in the
# database is again checked for if the UPDATE query returns 0.
(filtered._update(values) > 0 or filtered.exists())
)


if (self._proc is not None
# has the child process finished?
and self._returncode is None
# the child process has finished, but the
# transport hasn't been notified yet?
and self._proc.poll() is None):
pass

if (self._proc
# has the child process finished?
* self._returncode
# the child process has finished, but the
# transport hasn't been notified yet?
+ self._proc.poll()):
pass
44 changes: 44 additions & 0 deletions crates/ruff_python_formatter/src/comments/placement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ fn handle_enclosed_comment<'a>(
locator,
)
}
AnyNodeRef::ExprBoolOp(_) | AnyNodeRef::ExprCompare(_) => {
handle_trailing_binary_like_comment(comment, locator)
}
AnyNodeRef::Keyword(keyword) => handle_keyword_comment(comment, keyword, locator),
AnyNodeRef::PatternKeyword(pattern_keyword) => {
handle_pattern_keyword_comment(comment, pattern_keyword, locator)
Expand Down Expand Up @@ -836,6 +839,47 @@ fn handle_trailing_binary_expression_left_or_operator_comment<'a>(
}
}

/// Attaches comments between two bool or compare expression operands to the preceding operand if the comment is before the operator.
///
/// ```python
/// a = (
/// 5 > 3
/// # trailing comment
/// and 3 == 3
/// )
/// ```
fn handle_trailing_binary_like_comment<'a>(
comment: DecoratedComment<'a>,
locator: &Locator,
) -> CommentPlacement<'a> {
debug_assert!(
comment.enclosing_node().is_expr_bool_op() || comment.enclosing_node().is_expr_compare()
);

// Only if there's a preceding node (in which case, the preceding node is `left` or middle node).
let (Some(left_operand), Some(right_operand)) =
(comment.preceding_node(), comment.following_node())
else {
return CommentPlacement::Default(comment);
};

let between_operands_range = TextRange::new(left_operand.end(), right_operand.start());

let mut tokens = SimpleTokenizer::new(locator.contents(), between_operands_range)
.skip_trivia()
.skip_while(|token| token.kind == SimpleTokenKind::RParen);
let operator_offset = tokens
.next()
.expect("Expected a token for the operator")
.start();

if comment.end() < operator_offset {
CommentPlacement::trailing(left_operand, comment)
} else {
CommentPlacement::Default(comment)
}
}

/// Handles own line comments on the module level before a class or function statement.
/// A comment only becomes the leading comment of a class or function if it isn't separated by an empty
/// line from the class. Comments that are separated by at least one empty line from the header of the
Expand Down
Loading

0 comments on commit 1e6df19

Please sign in to comment.