Accept any Into<AnyNodeRef> as Comments arguments (#5205)

This commit is contained in:
Micha Reiser 2023-06-20 18:49:21 +02:00 committed by GitHub
parent 6f7d3cc798
commit b369288833
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 73 additions and 41 deletions

View file

@ -260,76 +260,109 @@ impl<'a> Comments<'a> {
} }
#[inline] #[inline]
pub(crate) fn has_comments(&self, node: AnyNodeRef) -> bool { pub(crate) fn has_comments<T>(&self, node: T) -> bool
self.data.comments.has(&NodeRefEqualityKey::from_ref(node)) where
T: Into<AnyNodeRef<'a>>,
{
self.data
.comments
.has(&NodeRefEqualityKey::from_ref(node.into()))
} }
/// Returns `true` if the given `node` has any [leading comments](self#leading-comments). /// Returns `true` if the given `node` has any [leading comments](self#leading-comments).
#[inline] #[inline]
pub(crate) fn has_leading_comments(&self, node: AnyNodeRef) -> bool { pub(crate) fn has_leading_comments<T>(&self, node: T) -> bool
where
T: Into<AnyNodeRef<'a>>,
{
!self.leading_comments(node).is_empty() !self.leading_comments(node).is_empty()
} }
/// Returns the `node`'s [leading comments](self#leading-comments). /// Returns the `node`'s [leading comments](self#leading-comments).
#[inline] #[inline]
pub(crate) fn leading_comments(&self, node: AnyNodeRef<'a>) -> &[SourceComment] { pub(crate) fn leading_comments<T>(&self, node: T) -> &[SourceComment]
where
T: Into<AnyNodeRef<'a>>,
{
self.data self.data
.comments .comments
.leading(&NodeRefEqualityKey::from_ref(node)) .leading(&NodeRefEqualityKey::from_ref(node.into()))
} }
/// Returns `true` if node has any [dangling comments](self#dangling-comments). /// Returns `true` if node has any [dangling comments](self#dangling-comments).
pub(crate) fn has_dangling_comments(&self, node: AnyNodeRef<'a>) -> bool { pub(crate) fn has_dangling_comments<T>(&self, node: T) -> bool
where
T: Into<AnyNodeRef<'a>>,
{
!self.dangling_comments(node).is_empty() !self.dangling_comments(node).is_empty()
} }
/// Returns the [dangling comments](self#dangling-comments) of `node` /// Returns the [dangling comments](self#dangling-comments) of `node`
pub(crate) fn dangling_comments(&self, node: AnyNodeRef<'a>) -> &[SourceComment] { pub(crate) fn dangling_comments<T>(&self, node: T) -> &[SourceComment]
where
T: Into<AnyNodeRef<'a>>,
{
self.data self.data
.comments .comments
.dangling(&NodeRefEqualityKey::from_ref(node)) .dangling(&NodeRefEqualityKey::from_ref(node.into()))
} }
/// Returns the `node`'s [trailing comments](self#trailing-comments). /// Returns the `node`'s [trailing comments](self#trailing-comments).
#[inline] #[inline]
pub(crate) fn trailing_comments(&self, node: AnyNodeRef<'a>) -> &[SourceComment] { pub(crate) fn trailing_comments<T>(&self, node: T) -> &[SourceComment]
where
T: Into<AnyNodeRef<'a>>,
{
self.data self.data
.comments .comments
.trailing(&NodeRefEqualityKey::from_ref(node)) .trailing(&NodeRefEqualityKey::from_ref(node.into()))
} }
/// Returns `true` if the given `node` has any [trailing comments](self#trailing-comments). /// Returns `true` if the given `node` has any [trailing comments](self#trailing-comments).
#[inline] #[inline]
pub(crate) fn has_trailing_comments(&self, node: AnyNodeRef) -> bool { pub(crate) fn has_trailing_comments<T>(&self, node: T) -> bool
where
T: Into<AnyNodeRef<'a>>,
{
!self.trailing_comments(node).is_empty() !self.trailing_comments(node).is_empty()
} }
/// Returns `true` if the given `node` has any [trailing own line comments](self#trailing-comments). /// Returns `true` if the given `node` has any [trailing own line comments](self#trailing-comments).
#[inline] #[inline]
pub(crate) fn has_trailing_own_line_comments(&self, node: AnyNodeRef) -> bool { pub(crate) fn has_trailing_own_line_comments<T>(&self, node: T) -> bool
where
T: Into<AnyNodeRef<'a>>,
{
self.trailing_comments(node) self.trailing_comments(node)
.iter() .iter()
.any(|comment| comment.position().is_own_line()) .any(|comment| comment.position().is_own_line())
} }
/// Returns an iterator over the [leading](self#leading-comments) and [trailing comments](self#trailing-comments) of `node`. /// Returns an iterator over the [leading](self#leading-comments) and [trailing comments](self#trailing-comments) of `node`.
pub(crate) fn leading_trailing_comments( pub(crate) fn leading_trailing_comments<T>(
&self, &self,
node: AnyNodeRef<'a>, node: T,
) -> impl Iterator<Item = &SourceComment> { ) -> impl Iterator<Item = &SourceComment>
where
T: Into<AnyNodeRef<'a>>,
{
let node = node.into();
self.leading_comments(node) self.leading_comments(node)
.iter() .iter()
.chain(self.trailing_comments(node).iter()) .chain(self.trailing_comments(node).iter())
} }
/// Returns an iterator over the [leading](self#leading-comments), [dangling](self#dangling-comments), and [trailing](self#trailing) comments of `node`. /// Returns an iterator over the [leading](self#leading-comments), [dangling](self#dangling-comments), and [trailing](self#trailing) comments of `node`.
pub(crate) fn leading_dangling_trailing_comments( pub(crate) fn leading_dangling_trailing_comments<T>(
&self, &self,
node: AnyNodeRef<'a>, node: T,
) -> impl Iterator<Item = &SourceComment> { ) -> impl Iterator<Item = &SourceComment>
where
T: Into<AnyNodeRef<'a>>,
{
self.data self.data
.comments .comments
.parts(&NodeRefEqualityKey::from_ref(node)) .parts(&NodeRefEqualityKey::from_ref(node.into()))
} }
#[inline(always)] #[inline(always)]

View file

@ -91,7 +91,7 @@ impl FormatNodeRule<ExprBinOp> for FormatExprBinOp {
)?; )?;
// Format the operator on its own line if the right side has any leading comments. // Format the operator on its own line if the right side has any leading comments.
if comments.has_leading_comments(right.as_ref().into()) { if comments.has_leading_comments(right.as_ref()) {
write!(f, [hard_line_break()])?; write!(f, [hard_line_break()])?;
} else if needs_space { } else if needs_space {
write!(f, [space()])?; write!(f, [space()])?;

View file

@ -35,7 +35,7 @@ impl Format<PyFormatContext<'_>> for KeyValuePair<'_> {
) )
} else { } else {
let comments = f.context().comments().clone(); let comments = f.context().comments().clone();
let leading_value_comments = comments.leading_comments(self.value.into()); let leading_value_comments = comments.leading_comments(self.value);
write!( write!(
f, f,
[ [

View file

@ -19,7 +19,7 @@ impl FormatNodeRule<ExprList> for FormatExprList {
} = item; } = item;
let comments = f.context().comments().clone(); let comments = f.context().comments().clone();
let dangling = comments.dangling_comments(item.into()); let dangling = comments.dangling_comments(item);
// The empty list is special because there can be dangling comments, and they can be in two // The empty list is special because there can be dangling comments, and they can be in two
// positions: // positions:

View file

@ -1,3 +1,7 @@
use crate::comments::{
dangling_node_comments, leading_node_comments, trailing_node_comments, Comments,
};
use crate::context::PyFormatContext;
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use ruff_formatter::prelude::*; use ruff_formatter::prelude::*;
use ruff_formatter::{format, write}; use ruff_formatter::{format, write};
@ -10,11 +14,6 @@ use rustpython_parser::lexer::lex;
use rustpython_parser::{parse_tokens, Mode}; use rustpython_parser::{parse_tokens, Mode};
use std::borrow::Cow; use std::borrow::Cow;
use crate::comments::{
dangling_node_comments, leading_node_comments, trailing_node_comments, Comments,
};
use crate::context::PyFormatContext;
pub(crate) mod builders; pub(crate) mod builders;
pub mod cli; pub mod cli;
mod comments; mod comments;
@ -437,9 +436,10 @@ def with_leading_comment(): ...
// Uncomment the `dbg` to print the IR. // Uncomment the `dbg` to print the IR.
// Use `dbg_write!(f, []) instead of `write!(f, [])` in your formatting code to print some IR // Use `dbg_write!(f, []) instead of `write!(f, [])` in your formatting code to print some IR
// inside of a `Format` implementation // inside of a `Format` implementation
// dbg!(formatted // use ruff_formatter::FormatContext;
// formatted
// .document() // .document()
// .display(formatted.context().source_code())); // .display(formatted.context().source_code());
// dbg!(formatted // dbg!(formatted
// .context() // .context()

View file

@ -1,7 +1,7 @@
#[allow(unused_imports)] #[allow(unused_imports)]
pub(crate) use crate::{ pub(crate) use crate::{
builders::PyFormatterExtensions, AsFormat, FormattedIterExt as _, IntoFormat, PyFormatContext, builders::PyFormatterExtensions, AsFormat, FormatNodeRule, FormattedIterExt as _, IntoFormat,
PyFormatter, PyFormatContext, PyFormatter,
}; };
#[allow(unused_imports)] #[allow(unused_imports)]
pub(crate) use ruff_formatter::prelude::*; pub(crate) use ruff_formatter::prelude::*;

View file

@ -37,7 +37,7 @@ impl FormatRule<AnyFunctionDefinition<'_>, PyFormatContext<'_>> for FormatAnyFun
) -> FormatResult<()> { ) -> FormatResult<()> {
let comments = f.context().comments().clone(); let comments = f.context().comments().clone();
let dangling_comments = comments.dangling_comments(item.into()); let dangling_comments = comments.dangling_comments(item);
let trailing_definition_comments_start = let trailing_definition_comments_start =
dangling_comments.partition_point(|comment| comment.position().is_own_line()); dangling_comments.partition_point(|comment| comment.position().is_own_line());

View file

@ -23,7 +23,7 @@ impl FormatNodeRule<StmtIf> for FormatStmtIf {
} = current_statement; } = current_statement;
let first_statement = body.first().ok_or(FormatError::SyntaxError)?; let first_statement = body.first().ok_or(FormatError::SyntaxError)?;
let trailing = comments.dangling_comments(current_statement.into()); let trailing = comments.dangling_comments(current_statement);
let trailing_if_comments_end = trailing let trailing_if_comments_end = trailing
.partition_point(|comment| comment.slice().start() < first_statement.start()); .partition_point(|comment| comment.slice().start() < first_statement.start());
@ -32,7 +32,7 @@ impl FormatNodeRule<StmtIf> for FormatStmtIf {
trailing.split_at(trailing_if_comments_end); trailing.split_at(trailing_if_comments_end);
if current.is_elif() { if current.is_elif() {
let elif_leading = comments.leading_comments(current_statement.into()); let elif_leading = comments.leading_comments(current_statement);
// Manually format the leading comments because the formatting bypasses `NodeRule::fmt` // Manually format the leading comments because the formatting bypasses `NodeRule::fmt`
write!( write!(
f, f,

View file

@ -96,13 +96,12 @@ impl FormatRule<Suite, PyFormatContext<'_>> for FormatSuite {
// the leading comment. This is why the suite handling counts the lines before the // the leading comment. This is why the suite handling counts the lines before the
// start of the next statement or before the first leading comments for compound statements. // start of the next statement or before the first leading comments for compound statements.
let separator = format_with(|f| { let separator = format_with(|f| {
let start = if let Some(first_leading) = let start =
comments.leading_comments(statement.into()).first() if let Some(first_leading) = comments.leading_comments(statement).first() {
{ first_leading.slice().start()
first_leading.slice().start() } else {
} else { statement.start()
statement.start() };
};
match lines_before(start, source) { match lines_before(start, source) {
0 | 1 => hard_line_break().fmt(f), 0 | 1 => hard_line_break().fmt(f),