Split implicit concatenated strings before binary expressions (#7145)

This commit is contained in:
Micha Reiser 2023-09-08 08:51:26 +02:00 committed by GitHub
parent 9671922e40
commit e376c3ff7e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 1067 additions and 366 deletions

View file

@ -102,84 +102,60 @@ impl Format<PyFormatContext<'_>> for FormatLeadingAlternateBranchComments<'_> {
}
}
/// Formats the trailing comments of `node`
pub(crate) fn trailing_node_comments<T>(node: &T) -> FormatTrailingComments
where
T: AstNode,
{
FormatTrailingComments::Node(node.as_any_node_ref())
}
/// Formats the passed comments as trailing comments
pub(crate) fn trailing_comments(comments: &[SourceComment]) -> FormatTrailingComments {
FormatTrailingComments::Comments(comments)
FormatTrailingComments(comments)
}
pub(crate) enum FormatTrailingComments<'a> {
Node(AnyNodeRef<'a>),
Comments(&'a [SourceComment]),
}
pub(crate) struct FormatTrailingComments<'a>(&'a [SourceComment]);
impl Format<PyFormatContext<'_>> for FormatTrailingComments<'_> {
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
fn write_trailing_comments(
comments: &[SourceComment],
f: &mut PyFormatter,
) -> FormatResult<()> {
let mut has_trailing_own_line_comment = false;
let mut has_trailing_own_line_comment = false;
for trailing in comments.iter().filter(|comment| comment.is_unformatted()) {
has_trailing_own_line_comment |= trailing.line_position().is_own_line();
for trailing in self.0.iter().filter(|comment| comment.is_unformatted()) {
has_trailing_own_line_comment |= trailing.line_position().is_own_line();
if has_trailing_own_line_comment {
let lines_before_comment = lines_before(trailing.start(), f.context().source());
if has_trailing_own_line_comment {
let lines_before_comment = lines_before(trailing.start(), f.context().source());
// A trailing comment at the end of a body or list
// ```python
// def test():
// pass
//
// # Some comment
// ```
write!(
f,
[
line_suffix(
&format_args![
empty_lines(lines_before_comment),
format_comment(trailing)
],
// Reserving width isn't necessary because we don't split
// comments and the empty lines expand any enclosing group.
0
),
expand_parent()
]
)?;
} else {
// A trailing comment at the end of a line has a reserved width to
// consider during line measurement.
// ```python
// tup = (
// "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
// ) # Some comment
// ```
trailing_end_of_line_comment(trailing).fmt(f)?;
}
trailing.mark_formatted();
// A trailing comment at the end of a body or list
// ```python
// def test():
// pass
//
// # Some comment
// ```
write!(
f,
[
line_suffix(
&format_args![
empty_lines(lines_before_comment),
format_comment(trailing)
],
// Reserving width isn't necessary because we don't split
// comments and the empty lines expand any enclosing group.
0
),
expand_parent()
]
)?;
} else {
// A trailing comment at the end of a line has a reserved width to
// consider during line measurement.
// ```python
// tup = (
// "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
// ) # Some comment
// ```
trailing_end_of_line_comment(trailing).fmt(f)?;
}
Ok(())
trailing.mark_formatted();
}
match self {
FormatTrailingComments::Node(node) => {
let comments = f.context().comments().clone();
write_trailing_comments(comments.trailing(*node), f)
}
FormatTrailingComments::Comments(comments) => write_trailing_comments(comments, f),
}
Ok(())
}
}

View file

@ -87,24 +87,22 @@
//!
//! It is possible to add an additional optional label to [`SourceComment`] If ever the need arises to distinguish two *dangling comments* in the formatting logic,
use ruff_text_size::{Ranged, TextRange};
use std::cell::Cell;
use std::fmt::Debug;
use std::rc::Rc;
use ruff_python_ast::Mod;
pub(crate) use format::{
dangling_comments, dangling_node_comments, dangling_open_parenthesis_comments,
leading_alternate_branch_comments, leading_comments, leading_node_comments, trailing_comments,
trailing_node_comments,
};
use ruff_formatter::{SourceCode, SourceCodeSlice};
use ruff_python_ast::node::AnyNodeRef;
use ruff_python_ast::visitor::preorder::{PreorderVisitor, TraversalSignal};
use ruff_python_ast::Mod;
use ruff_python_index::CommentRanges;
use ruff_python_trivia::PythonWhitespace;
use ruff_source_file::Locator;
use ruff_text_size::{Ranged, TextRange};
use crate::comments::debug::{DebugComment, DebugComments};
use crate::comments::map::{LeadingDanglingTrailing, MultiMap};
@ -527,12 +525,12 @@ impl<'a> PreorderVisitor<'a> for MarkVerbatimCommentsAsFormattedVisitor<'a> {
#[cfg(test)]
mod tests {
use insta::assert_debug_snapshot;
use ruff_python_ast::Mod;
use ruff_python_parser::lexer::lex;
use ruff_python_parser::{parse_tokens, Mode};
use ruff_formatter::SourceCode;
use ruff_python_ast::Mod;
use ruff_python_index::{CommentRanges, CommentRangesBuilder};
use ruff_python_parser::lexer::lex;
use ruff_python_parser::{parse_tokens, Mode};
use crate::comments::Comments;