From 68d52da43b73a570b50c37c5b324eaabdc8d8c69 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Fri, 9 Jun 2023 11:09:45 +0200 Subject: [PATCH] Track formatted comments (#4979) --- .../src/comments/debug.rs | 30 +++++------ .../src/comments/format.rs | 15 ++++-- .../ruff_python_formatter/src/comments/mod.rs | 53 +++++++++++-------- .../src/comments/visitor.rs | 7 +-- crates/ruff_python_formatter/src/other/arg.rs | 35 +----------- .../src/other/arguments.rs | 5 +- 6 files changed, 60 insertions(+), 85 deletions(-) diff --git a/crates/ruff_python_formatter/src/comments/debug.rs b/crates/ruff_python_formatter/src/comments/debug.rs index 6e37ac5ff6..6bb123db7d 100644 --- a/crates/ruff_python_formatter/src/comments/debug.rs +++ b/crates/ruff_python_formatter/src/comments/debug.rs @@ -206,32 +206,26 @@ break; comments_map.push_leading( continue_statement.as_ref().into(), - SourceComment { - slice: source_code.slice(TextRange::at(TextSize::new(0), TextSize::new(17))), - #[cfg(debug_assertions)] - formatted: std::cell::Cell::new(false), - position: CommentTextPosition::OwnLine, - }, + SourceComment::new( + source_code.slice(TextRange::at(TextSize::new(0), TextSize::new(17))), + CommentTextPosition::OwnLine, + ), ); comments_map.push_trailing( continue_statement.as_ref().into(), - SourceComment { - slice: source_code.slice(TextRange::at(TextSize::new(28), TextSize::new(10))), - #[cfg(debug_assertions)] - formatted: std::cell::Cell::new(false), - position: CommentTextPosition::EndOfLine, - }, + SourceComment::new( + source_code.slice(TextRange::at(TextSize::new(28), TextSize::new(10))), + CommentTextPosition::EndOfLine, + ), ); comments_map.push_leading( break_statement.as_ref().into(), - SourceComment { - slice: source_code.slice(TextRange::at(TextSize::new(39), TextSize::new(15))), - #[cfg(debug_assertions)] - formatted: std::cell::Cell::new(false), - position: CommentTextPosition::OwnLine, - }, + SourceComment::new( + source_code.slice(TextRange::at(TextSize::new(39), TextSize::new(15))), + CommentTextPosition::OwnLine, + ), ); let comments = Comments::new(comments_map); diff --git a/crates/ruff_python_formatter/src/comments/format.rs b/crates/ruff_python_formatter/src/comments/format.rs index 7c57709503..70eb87f679 100644 --- a/crates/ruff_python_formatter/src/comments/format.rs +++ b/crates/ruff_python_formatter/src/comments/format.rs @@ -36,7 +36,10 @@ impl Format> for FormatLeadingComments<'_> { FormatLeadingComments::Comments(comments) => comments, }; - for comment in leading_comments { + for comment in leading_comments + .iter() + .filter(|comment| comment.is_unformatted()) + { let slice = comment.slice(); let lines_after_comment = lines_after(slice.end(), f.context().contents()); @@ -127,7 +130,10 @@ impl Format> for FormatTrailingComments<'_> { let mut has_trailing_own_line_comment = false; - for trailing in trailing_comments { + for trailing in trailing_comments + .iter() + .filter(|comment| comment.is_unformatted()) + { let slice = trailing.slice(); has_trailing_own_line_comment |= trailing.position().is_own_line(); @@ -198,7 +204,10 @@ impl Format> for FormatDanglingComments<'_> { }; let mut first = true; - for comment in dangling_comments { + for comment in dangling_comments + .iter() + .filter(|comment| comment.is_unformatted()) + { if first && comment.position().is_end_of_line() { write!(f, [space(), space()])?; } diff --git a/crates/ruff_python_formatter/src/comments/mod.rs b/crates/ruff_python_formatter/src/comments/mod.rs index 9267cdd899..171073d565 100644 --- a/crates/ruff_python_formatter/src/comments/mod.rs +++ b/crates/ruff_python_formatter/src/comments/mod.rs @@ -87,17 +87,6 @@ //! //! 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 rustpython_parser::ast::Mod; -use std::fmt::Debug; -use std::rc::Rc; - -mod debug; -mod format; -mod map; -mod node_key; -mod placement; -mod visitor; - use crate::comments::debug::{DebugComment, DebugComments}; use crate::comments::map::MultiMap; use crate::comments::node_key::NodeRefEqualityKey; @@ -109,40 +98,60 @@ pub(crate) use format::{ use ruff_formatter::{SourceCode, SourceCodeSlice}; use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::source_code::CommentRanges; +use rustpython_parser::ast::Mod; +use std::cell::Cell; +use std::fmt::Debug; +use std::rc::Rc; + +mod debug; +mod format; +mod map; +mod node_key; +mod placement; +mod visitor; /// A comment in the source document. #[derive(Debug, Clone)] pub(crate) struct SourceComment { /// The location of the comment in the source document. slice: SourceCodeSlice, - /// Whether the comment has been formatted or not. - #[cfg(debug_assertions)] - formatted: std::cell::Cell, - + formatted: Cell, position: CommentTextPosition, } impl SourceComment { + fn new(slice: SourceCodeSlice, position: CommentTextPosition) -> Self { + Self { + slice, + position, + formatted: Cell::new(false), + } + } + /// Returns the location of the comment in the original source code. /// Allows retrieving the text of the comment. - pub(crate) fn slice(&self) -> &SourceCodeSlice { + pub(crate) const fn slice(&self) -> &SourceCodeSlice { &self.slice } - pub(crate) fn position(&self) -> CommentTextPosition { + pub(crate) const fn position(&self) -> CommentTextPosition { self.position } - #[cfg(not(debug_assertions))] - #[inline(always)] - pub(crate) fn mark_formatted(&self) {} - /// Marks the comment as formatted - #[cfg(debug_assertions)] pub(crate) fn mark_formatted(&self) { self.formatted.set(true); } + + /// If the comment has already been formatted + pub(crate) fn is_formatted(&self) -> bool { + self.formatted.get() + } + + pub(crate) fn is_unformatted(&self) -> bool { + !self.is_formatted() + } } impl SourceComment { diff --git a/crates/ruff_python_formatter/src/comments/visitor.rs b/crates/ruff_python_formatter/src/comments/visitor.rs index d0aef540df..76f80febfd 100644 --- a/crates/ruff_python_formatter/src/comments/visitor.rs +++ b/crates/ruff_python_formatter/src/comments/visitor.rs @@ -420,12 +420,7 @@ impl<'a> DecoratedComment<'a> { impl From> for SourceComment { fn from(decorated: DecoratedComment) -> Self { - Self { - slice: decorated.slice, - position: decorated.text_position, - #[cfg(debug_assertions)] - formatted: std::cell::Cell::new(false), - } + Self::new(decorated.slice, decorated.text_position) } } diff --git a/crates/ruff_python_formatter/src/other/arg.rs b/crates/ruff_python_formatter/src/other/arg.rs index d63fa04f5f..a0eebd3a96 100644 --- a/crates/ruff_python_formatter/src/other/arg.rs +++ b/crates/ruff_python_formatter/src/other/arg.rs @@ -1,25 +1,11 @@ -use crate::comments::leading_node_comments; use crate::prelude::*; use crate::FormatNodeRule; -use ruff_formatter::{write, FormatRuleWithOptions}; +use ruff_formatter::write; use ruff_text_size::{TextLen, TextRange}; use rustpython_parser::ast::Arg; #[derive(Default)] -pub struct FormatArg { - kind: ArgumentKind, -} - -#[derive(Copy, Clone, Debug, Default)] -pub enum ArgumentKind { - /// Positional only, regular argument, or a keyword only argument. - #[default] - Normal, - /// A `*args` arguments - Varg, - /// A `**kwargs` argument - Kwarg, -} +pub struct FormatArg; impl FormatNodeRule for FormatArg { fn fmt_fields(&self, item: &Arg, f: &mut PyFormatter) -> FormatResult<()> { @@ -46,21 +32,4 @@ impl FormatNodeRule for FormatArg { Ok(()) } - - fn fmt_leading_comments(&self, node: &Arg, f: &mut PyFormatter) -> FormatResult<()> { - match self.kind { - ArgumentKind::Normal => leading_node_comments(node).fmt(f), - // Formatted as part of the `Arguments` to avoid emitting leading comments between the `*` and the argument. - ArgumentKind::Kwarg | ArgumentKind::Varg => Ok(()), - } - } -} - -impl FormatRuleWithOptions> for FormatArg { - type Options = ArgumentKind; - - fn with_options(mut self, options: Self::Options) -> Self { - self.kind = options; - self - } } diff --git a/crates/ruff_python_formatter/src/other/arguments.rs b/crates/ruff_python_formatter/src/other/arguments.rs index bd7913db4f..19f8107f00 100644 --- a/crates/ruff_python_formatter/src/other/arguments.rs +++ b/crates/ruff_python_formatter/src/other/arguments.rs @@ -1,6 +1,5 @@ use crate::comments::{dangling_node_comments, leading_node_comments}; use crate::context::NodeLevel; -use crate::other::arg::ArgumentKind; use crate::prelude::*; use crate::trivia::{first_non_trivia_token, SimpleTokenizer, Token, TokenKind}; use crate::FormatNodeRule; @@ -63,7 +62,7 @@ impl FormatNodeRule for FormatArguments { joiner.entry(&format_args![ leading_node_comments(vararg.as_ref()), text("*"), - vararg.format().with_options(ArgumentKind::Varg) + vararg.format() ]); last_node = Some(vararg.as_any_node_ref()); } @@ -90,7 +89,7 @@ impl FormatNodeRule for FormatArguments { joiner.entry(&format_args![ leading_node_comments(kwarg.as_ref()), text("**"), - kwarg.format().with_options(ArgumentKind::Kwarg) + kwarg.format() ]); last_node = Some(kwarg.as_any_node_ref()); }