Skip to content

Commit

Permalink
Keep trailing part comment associated with its part
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaReiser committed Jan 10, 2025
1 parent d0b2bbd commit eef2e67
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 9 deletions.
33 changes: 30 additions & 3 deletions crates/ruff_python_ast/src/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::iter::FusedIterator;
use ruff_text_size::{Ranged, TextRange};

use crate::{
self as ast, AnyNodeRef, AnyStringFlags, Expr, ExprBytesLiteral, ExprFString,
self as ast, AnyNode, AnyNodeRef, AnyStringFlags, Expr, ExprBytesLiteral, ExprFString,
ExprStringLiteral, StringFlags,
};

Expand Down Expand Up @@ -407,13 +407,13 @@ pub enum StringLike<'a> {
FString(&'a ast::ExprFString),
}

impl StringLike<'_> {
impl<'a> StringLike<'a> {
pub const fn is_fstring(self) -> bool {
matches!(self, Self::FString(_))
}

/// Returns an iterator over the [`StringLikePart`] contained in this string-like expression.
pub fn parts(&self) -> StringLikePartIter<'_> {
pub fn parts(&self) -> StringLikePartIter<'a> {
match self {
StringLike::String(expr) => StringLikePartIter::String(expr.value.iter()),
StringLike::Bytes(expr) => StringLikePartIter::Bytes(expr.value.iter()),
Expand All @@ -429,6 +429,14 @@ impl StringLike<'_> {
Self::FString(ExprFString { value, .. }) => value.is_implicit_concatenated(),
}
}

pub const fn as_expression_ref(self) -> ExpressionRef<'a> {
match self {
StringLike::String(expr) => ExpressionRef::StringLiteral(expr),
StringLike::Bytes(expr) => ExpressionRef::BytesLiteral(expr),
StringLike::FString(expr) => ExpressionRef::FString(expr),
}
}
}

impl<'a> From<&'a ast::ExprStringLiteral> for StringLike<'a> {
Expand Down Expand Up @@ -488,6 +496,19 @@ impl<'a> TryFrom<&'a Expr> for StringLike<'a> {
}
}

impl<'a> TryFrom<AnyNodeRef<'a>> for StringLike<'a> {
type Error = ();

fn try_from(value: AnyNodeRef<'a>) -> Result<Self, Self::Error> {
match value {
AnyNodeRef::ExprStringLiteral(value) => Ok(Self::String(value)),
AnyNodeRef::ExprBytesLiteral(value) => Ok(Self::Bytes(value)),
AnyNodeRef::ExprFString(value) => Ok(Self::FString(value)),
_ => Err(()),
}
}
}

impl Ranged for StringLike<'_> {
fn range(&self) -> TextRange {
match self {
Expand Down Expand Up @@ -561,6 +582,12 @@ impl<'a> From<&'a ast::FString> for StringLikePart<'a> {

impl<'a> From<&StringLikePart<'a>> for AnyNodeRef<'a> {
fn from(value: &StringLikePart<'a>) -> Self {
AnyNodeRef::from(*value)
}
}

impl<'a> From<StringLikePart<'a>> for AnyNodeRef<'a> {
fn from(value: StringLikePart<'a>) -> Self {
match value {
StringLikePart::String(part) => AnyNodeRef::StringLiteral(part),
StringLikePart::Bytes(part) => AnyNodeRef::BytesLiteral(part),
Expand Down
40 changes: 36 additions & 4 deletions crates/ruff_python_formatter/src/comments/placement.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
use std::cmp::Ordering;

use ast::helpers::comment_indentation_after;
use itertools::Itertools;
use ruff_python_ast::parenthesize::parenthesized_range;
use ruff_python_ast::whitespace::indentation;
use ruff_python_ast::{
self as ast, AnyNodeRef, Comprehension, Expr, ModModule, Parameter, Parameters,
self as ast, AnyNodeRef, Comprehension, Expr, ExpressionRef, ModModule, Parameter, Parameters,
StringLike,
};
use ruff_python_trivia::{
find_only_token_in_range, first_non_trivia_token, indentation_at_offset, BackwardsTokenizer,
CommentRanges, SimpleToken, SimpleTokenKind, SimpleTokenizer,
};
use ruff_source_file::LineRanges;
use ruff_text_size::{Ranged, TextLen, TextRange};
use ruff_text_size::{Ranged, TextLen, TextRange, TextSlice};
use std::cmp::Ordering;

use crate::comments::visitor::{CommentPlacement, DecoratedComment};
use crate::expression::expr_slice::{assign_comment_in_slice, ExprSliceCommentSection};
use crate::expression::parentheses::is_expression_parenthesized;
use crate::other::parameters::{
assign_argument_separator_comment_placement, find_parameter_separators,
};
Expand Down Expand Up @@ -194,6 +197,35 @@ fn handle_enclosed_comment<'a>(
comment_ranges: &CommentRanges,
source: &str,
) -> CommentPlacement<'a> {
if let Some(preceding) = comment.preceding_node() {
if let Ok(string_like) = StringLike::try_from(preceding) {
let has_line_break_in_between = string_like
.parts()
.tuple_windows()
.any(|(a, b)| source.contains_line_break(TextRange::new(a.end(), b.start())));

if has_line_break_in_between
&& comment.line_position().is_end_of_line()
&& is_expression_parenthesized(
string_like.as_expression_ref(),
comment_ranges,
source,
)
{
if let Some(last_part) = string_like.parts().last() {
let range = TextRange::new(last_part.end(), comment.start());

if !SimpleTokenizer::new(source, range)
.skip_trivia()
.any(|token| token.kind() == SimpleTokenKind::RParen)
{
return CommentPlacement::trailing(AnyNodeRef::from(last_part), comment);
}
}
}
}
}

match comment.enclosing_node() {
AnyNodeRef::Parameters(parameters) => {
handle_parameters_separator_comment(comment, parameters, source).or_else(|comment| {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,8 @@ result_f = (
)

(
f"{1}{2}" # comment 3
f"{1}"
f"{2}" # comment 3
)

(
Expand Down Expand Up @@ -1550,7 +1551,8 @@ result_f = (
)

(
f"{1}{2}" # comment 3
f"{1}"
f"{2}" # comment 3
)

(
Expand Down

0 comments on commit eef2e67

Please sign in to comment.