Skip to content

Commit

Permalink
formatter: comments inside dict unpacking
Browse files Browse the repository at this point in the history
handle comments between the `**` and the variable name when unpacking
dicts inside dict literals

can possibly be extended to function arguments, see inline comment
  • Loading branch information
davidszotten committed Jun 19, 2023
1 parent 4378cfe commit afd88a6
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@

{**d}

{**a, # leading
** # middle
b # trailing
}

{
** # middle with single item
b
}

{}

{1:2,}
Expand Down
68 changes: 68 additions & 0 deletions crates/ruff_python_formatter/src/comments/placement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub(super) fn place_comment<'a>(
handle_trailing_binary_expression_left_or_operator_comment(comment, locator)
})
.or_else(handle_leading_function_with_decorators_comment)
.or_else(|comment| handle_dict_unpacking_comment(comment, locator))
}

/// Handles leading comments in front of a match case or a trailing comment of the `match` statement.
Expand Down Expand Up @@ -888,6 +889,73 @@ fn handle_leading_function_with_decorators_comment(comment: DecoratedComment) ->
}
}

/// Handles comments between `**` and the variable name in dict unpacking
/// It attaches these to the appropriate value node
///
/// ```python
/// {
/// ** # comment between `**` and the variable name
/// value
/// ...
/// }
/// ```
fn handle_dict_unpacking_comment<'a>(
comment: DecoratedComment<'a>,
locator: &Locator,
) -> CommentPlacement<'a> {
match comment.enclosing_node() {
// TODO: can maybe also add AnyNodeRef::Arguments here, but tricky to test due to
// https://github.com/astral-sh/ruff/issues/5176
AnyNodeRef::ExprDict(_) => {}
_ => {
return CommentPlacement::Default(comment);
}
};
if let Some(following) = comment.following_node() {
let preceding_end = match comment.preceding_node() {
Some(preceding) => preceding.end(),
None => comment.enclosing_node().start(),
};
let mut tokens_before = SimpleTokenizer::new(
locator.contents(),
TextRange::new(preceding_end, comment.slice().start()),
)
.skip_trivia()
.peekable();

while let Some(it) = tokens_before.next() {
if it.kind == TokenKind::Star
&& tokens_before.peek().map(|t| t.kind) == Some(TokenKind::Star)
{
return CommentPlacement::trailing(following, comment);
}
}
}

if let Some(preceding) = comment.preceding_node() {
let following_start = match comment.following_node() {
Some(following) => following.start(),
None => comment.enclosing_node().end(),
};
let mut tokens_after = SimpleTokenizer::new(
locator.contents(),
TextRange::new(comment.slice().end(), following_start),
)
.skip_trivia()
.peekable();

while let Some(it) = tokens_after.next() {
if it.kind == TokenKind::Star
&& tokens_after.peek().map(|t| t.kind) == Some(TokenKind::Star)
{
return CommentPlacement::trailing(preceding, comment);
}
}
}

CommentPlacement::Default(comment)
}

/// Returns `true` if `right` is `Some` and `left` and `right` are referentially equal.
fn are_same_optional<'a, T>(left: AnyNodeRef, right: Option<T>) -> bool
where
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ expression: snapshot
{**d}
{**a, # leading
** # middle
b # trailing
}
{
** # middle with single item
b
}
{}
{1:2,}
Expand Down Expand Up @@ -46,6 +56,15 @@ mapping = {
{**d}
{
**a, # leading
**b, # middle # trailing
}
{
**b, # middle with single item
}
{}
{
Expand Down
4 changes: 4 additions & 0 deletions crates/ruff_python_formatter/src/trivia.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ pub(crate) enum TokenKind {
/// '/'
Slash,

/// '*'
Star,

/// Any other non trivia token. Always has a length of 1
Other,

Expand All @@ -181,6 +184,7 @@ impl TokenKind {
',' => TokenKind::Comma,
':' => TokenKind::Colon,
'/' => TokenKind::Slash,
'*' => TokenKind::Star,
_ => TokenKind::Other,
}
}
Expand Down

0 comments on commit afd88a6

Please sign in to comment.