diff --git a/Cargo.lock b/Cargo.lock index 603a1b28fa9..881ffa4a5e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1608,7 +1608,11 @@ name = "rome_formatter" version = "0.0.0" dependencies = [ "cfg-if", + "countme", "indexmap", + "rome_diagnostics", + "rome_js_parser", + "rome_js_syntax", "rome_rowan", "rustc-hash", "schemars", @@ -2859,6 +2863,7 @@ name = "xtask_bench" version = "0.0.0" dependencies = [ "ansi_rgb", + "countme", "criterion", "dhat", "humansize", diff --git a/crates/rome_formatter/Cargo.toml b/crates/rome_formatter/Cargo.toml index c288a1f6035..a8f910a590e 100644 --- a/crates/rome_formatter/Cargo.toml +++ b/crates/rome_formatter/Cargo.toml @@ -16,6 +16,12 @@ cfg-if = "1.0.0" indexmap = "1.8.2" schemars = { version = "0.8.10", optional = true } rustc-hash = "1.1.0" +countme = "3.0.1" + +[dev-dependencies] +rome_js_parser = { path = "../rome_js_parser"} +rome_js_syntax = { path = "../rome_js_syntax" } +rome_diagnostics = { path = "../rome_diagnostics" } [features] serde = ["dep:serde", "schemars", "rome_rowan/serde"] diff --git a/crates/rome_formatter/src/builders.rs b/crates/rome_formatter/src/builders.rs index 7fef20d8a04..d4158fcca85 100644 --- a/crates/rome_formatter/src/builders.rs +++ b/crates/rome_formatter/src/builders.rs @@ -1,15 +1,11 @@ use crate::prelude::*; -use crate::{ - format_element, write, Argument, Arguments, BufferSnapshot, FormatState, GroupId, TextRange, - TextSize, -}; +use crate::{format_element, write, Argument, Arguments, GroupId, TextRange, TextSize}; use crate::{Buffer, VecBuffer}; use rome_rowan::{Language, SyntaxNode, SyntaxToken, SyntaxTokenText, TextLen}; use std::borrow::Cow; use std::cell::Cell; use std::marker::PhantomData; use std::num::NonZeroU8; -use std::ops::Deref; /// A line break that only gets printed if the enclosing `Group` doesn't fit on a single line. /// It's omitted if the enclosing `Group` fits on a single line. @@ -457,73 +453,6 @@ impl Format for LineSuffixBoundary { } } -/// Marks some content as a comment trivia. -/// -/// This does not directly influence how this content will be printed, but some -/// parts of the formatter may chose to handle this element in a specific way -/// -/// ## Examples -/// -/// ``` -/// use rome_formatter::{format, write, format_args}; -/// use rome_formatter::prelude::*; -/// -/// let elements = format!( -/// SimpleFormatContext::default(), -/// [ -/// group(&format_args![ -/// comment(&format_args![text("// test"), hard_line_break()]), -/// format_with(|f| { -/// write!(f, [ -/// comment(&format_args![text("/* inline */"), hard_line_break()]).memoized(), -/// text("a"), -/// soft_line_break_or_space(), -/// ]) -/// }).memoized(), -/// text("b"), -/// soft_line_break_or_space(), -/// text("c") -/// ]) -/// ] -/// ).unwrap(); -/// -/// assert_eq!( -/// "// test\n/* inline */\na b c", -/// elements.print().as_code() -/// ); -/// ``` -#[inline] -pub fn comment(content: &Content) -> FormatComment -where - Content: Format, -{ - FormatComment { - content: Argument::new(content), - } -} - -#[derive(Copy, Clone)] -pub struct FormatComment<'a, Context> { - content: Argument<'a, Context>, -} - -impl Format for FormatComment<'_, Context> { - fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - let mut buffer = VecBuffer::new(f.state_mut()); - - buffer.write_fmt(Arguments::from(&self.content))?; - let content = buffer.into_vec(); - - f.write_element(FormatElement::Comment(content.into_boxed_slice())) - } -} - -impl std::fmt::Debug for FormatComment<'_, Context> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_tuple("Comment").field(&"{{content}}").finish() - } -} - /// Marks some content with a label. /// /// This does not directly influence how this content will be printed, but some @@ -1152,6 +1081,7 @@ pub struct BlockIndent<'a, Context> { enum IndentMode { Soft, Block, + SoftSpace, SoftLineOrSpace, } @@ -1162,7 +1092,9 @@ impl Format for BlockIndent<'_, Context> { match self.mode { IndentMode::Soft => write!(buffer, [soft_line_break()])?, IndentMode::Block => write!(buffer, [hard_line_break()])?, - IndentMode::SoftLineOrSpace => write!(buffer, [soft_line_break_or_space()])?, + IndentMode::SoftLineOrSpace | IndentMode::SoftSpace => { + write!(buffer, [soft_line_break_or_space()])? + } }; buffer.write_fmt(Arguments::from(&self.content))?; @@ -1179,6 +1111,7 @@ impl Format for BlockIndent<'_, Context> { match self.mode { IndentMode::Soft => write!(f, [soft_line_break()])?, IndentMode::Block => write!(f, [hard_line_break()])?, + IndentMode::SoftSpace => write!(f, [soft_line_break_or_space()])?, IndentMode::SoftLineOrSpace => {} } @@ -1192,12 +1125,77 @@ impl std::fmt::Debug for BlockIndent<'_, Context> { IndentMode::Soft => "SoftBlockIndent", IndentMode::Block => "HardBlockIndent", IndentMode::SoftLineOrSpace => "SoftLineIndentOrSpace", + IndentMode::SoftSpace => "SoftSpaceBlockIndent", }; f.debug_tuple(name).field(&"{{content}}").finish() } } +/// Adds spaces around the content if its enclosing group fits on a line, otherwise indents the content and separates it by line breaks. +/// +/// # Examples +/// +/// Adds line breaks and indents the content if the enclosing group doesn't fit on the line. +/// +/// ``` +/// use rome_formatter::{format, format_args, LineWidth, SimpleFormatOptions}; +/// use rome_formatter::prelude::*; +/// +/// let context = SimpleFormatContext::new(SimpleFormatOptions { +/// line_width: LineWidth::try_from(10).unwrap(), +/// ..SimpleFormatOptions::default() +/// }); +/// +/// let elements = format!(context, [ +/// group(&format_args![ +/// text("{"), +/// soft_space_or_block_indent(&format_args![ +/// text("aPropertyThatExceeds"), +/// text(":"), +/// space(), +/// text("'line width'"), +/// ]), +/// text("}") +/// ]) +/// ]).unwrap(); +/// +/// assert_eq!( +/// "{\n\taPropertyThatExceeds: 'line width'\n}", +/// elements.print().as_code() +/// ); +/// ``` +/// +/// Adds spaces around the content if the group fits on the line +/// ``` +/// use rome_formatter::{format, format_args}; +/// use rome_formatter::prelude::*; +/// +/// let elements = format!(SimpleFormatContext::default(), [ +/// group(&format_args![ +/// text("{"), +/// soft_space_or_block_indent(&format_args![ +/// text("a"), +/// text(":"), +/// space(), +/// text("5"), +/// ]), +/// text("}") +/// ]) +/// ]).unwrap(); +/// +/// assert_eq!( +/// "{ a: 5 }", +/// elements.print().as_code() +/// ); +/// ``` +pub fn soft_space_or_block_indent(content: &impl Format) -> BlockIndent { + BlockIndent { + content: Argument::new(content), + mode: IndentMode::SoftSpace, + } +} + /// Creates a logical `Group` around the content that should either consistently be printed on a single line /// or broken across multiple lines. /// @@ -1307,7 +1305,7 @@ impl Format for Group<'_, Context> { return f.write_fmt(Arguments::from(&self.content)); } - let mut buffer = GroupBuffer::new(f); + let mut buffer = VecBuffer::new(f.state_mut()); buffer.write_fmt(Arguments::from(&self.content))?; @@ -1322,9 +1320,7 @@ impl Format for Group<'_, Context> { let group = format_element::Group::new(content).with_id(self.group_id); - f.write_element(FormatElement::Group(group))?; - - Ok(()) + f.write_element(FormatElement::Group(group)) } } @@ -1338,154 +1334,6 @@ impl std::fmt::Debug for Group<'_, Context> { } } -/// Custom buffer implementation for `GroupElements` that moves the leading comments out of the group -/// to prevent that a leading line comment expands the token's enclosing group. -/// -/// # Examples -/// -/// ```javascript -/// /* a comment */ -/// [1] -/// ``` -/// -/// The `/* a comment */` belongs to the `[` group token that is part of a group wrapping the whole -/// `[1]` expression. It's important that the comment `/* a comment */` gets moved out of the group element -/// to avoid that the `[1]` group expands because of the line break inserted by the comment. -struct GroupBuffer<'inner, Context> { - inner: &'inner mut dyn Buffer, - - /// The group inner content - content: Vec, -} - -impl<'inner, Context> GroupBuffer<'inner, Context> { - fn new(inner: &'inner mut dyn Buffer) -> Self { - Self { - inner, - content: Vec::new(), - } - } - - fn into_vec(self) -> Vec { - self.content - } - - fn write_interned(&mut self, interned: Interned) -> FormatResult<()> { - debug_assert!(self.content.is_empty()); - - match interned.deref() { - FormatElement::Comment(_) => { - self.inner.write_element(FormatElement::Interned(interned)) - } - FormatElement::List(list) => { - let mut content_start = 0; - - for element in list.iter() { - match element { - element @ FormatElement::Comment(_) => { - content_start += 1; - // Cloning comments should be alright as they are rarely nested - // and the case where all elements of an interned data structure are comments - // are rare - self.inner.write_element(element.clone())?; - } - FormatElement::Interned(interned) => { - self.write_interned(interned.clone())?; - content_start += 1; - - if !self.content.is_empty() { - // Interned struct contained non-comment - break; - } - } - _ => { - // Found the first non-comment / nested interned element - break; - } - } - } - - // No leading comments, this group has no comments - if content_start == 0 { - self.content.push(FormatElement::Interned(interned)); - return Ok(()); - } - - let content = &list[content_start..]; - - // It is necessary to mutate the interned elements, write cloned elements - self.write_elements(content.iter().cloned()) - } - FormatElement::Interned(interned) => self.write_interned(interned.clone()), - _ => { - self.content.push(FormatElement::Interned(interned)); - Ok(()) - } - } - } -} - -impl Buffer for GroupBuffer<'_, Context> { - type Context = Context; - - fn write_element(&mut self, element: FormatElement) -> FormatResult<()> { - if self.content.is_empty() { - match element { - FormatElement::List(list) => { - self.write_elements(list.into_vec())?; - } - FormatElement::Interned(interned) => match Interned::try_unwrap(interned) { - Ok(owned) => self.write_element(owned)?, - Err(interned) => self.write_interned(interned)?, - }, - comment @ FormatElement::Comment { .. } => { - self.inner.write_element(comment)?; - } - element => self.content.push(element), - } - } else { - match element { - FormatElement::List(list) => { - self.content.extend(list.into_vec()); - } - element => self.content.push(element), - } - } - - Ok(()) - } - - fn elements(&self) -> &[FormatElement] { - &self.content - } - - fn state(&self) -> &FormatState { - self.inner.state() - } - - fn state_mut(&mut self) -> &mut FormatState { - self.inner.state_mut() - } - - fn snapshot(&self) -> BufferSnapshot { - BufferSnapshot::Any(Box::new(GroupElementsBufferSnapshot { - inner: self.inner.snapshot(), - content_len: self.content.len(), - })) - } - - fn restore_snapshot(&mut self, snapshot: BufferSnapshot) { - let snapshot = snapshot.unwrap_any::(); - self.inner.restore_snapshot(snapshot.inner); - self.content.truncate(snapshot.content_len); - } -} - -struct GroupElementsBufferSnapshot { - inner: BufferSnapshot, - content_len: usize, -} - /// IR element that forces the parent group to print in expanded mode. /// /// Has no effect if used outside of a group or element that introduce implicit groups (fill element). @@ -2213,9 +2061,9 @@ pub fn get_lines_before(next_node: &SyntaxNode) -> usize { leading_trivia .pieces() .take_while(|piece| { - // Stop at the first comment piece, the comment printer + // Stop at the first comment or skipped piece, the comment printer // will handle newlines between the comment and the node - !piece.is_comments() + !(piece.is_comments() || piece.is_skipped()) }) .filter(|piece| piece.is_newline()) .count() diff --git a/crates/rome_formatter/src/comments.rs b/crates/rome_formatter/src/comments.rs index d6c34cad742..80debabafe1 100644 --- a/crates/rome_formatter/src/comments.rs +++ b/crates/rome_formatter/src/comments.rs @@ -1,10 +1,90 @@ -use rome_rowan::{ - Direction, Language, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxTriviaPieceComments, - WalkEvent, -}; +//! Types for extracting and representing comments of a syntax tree. +//! +//! Most programming languages support comments allowing programmers to document their programs. Comments are different from other syntaxes because programming languages allow comments in almost any position, giving programmers great flexibility on where they can write comments: +//! +//! ```ignore +//! /** +//! * Documentation comment +//! */ +//! async /* comment */ function Test () // line comment +//! {/*inline*/} +//! ``` +//! +//! However, this flexibility makes formatting comments challenging because: +//! * The formatter must consistently place comments so that re-formatting the output yields the same result and does not create invalid syntax (line comments). +//! * It is essential that formatters place comments close to the syntax the programmer intended to document. However, the lack of rules regarding where comments are allowed and what syntax they document requires the use of heuristics to infer the documented syntax. +//! +//! This module strikes a balance between placing comments as closely as possible to their source location and reducing the complexity of formatting comments. It does so by associating comments per node rather than a token. This greatly reduces the combinations of possible comment positions but turns out to be, in practice, sufficiently precise to keep comments close to their source location. +//! +//! ## Node comments +//! +//! Comments are associated per node but get further distinguished on their location related to that node: +//! +//! ### Leading Comments +//! +//! A comment at the start of a node +//! +//! ```ignore +//! // Leading comment of the statement +//! console.log("test"); +//! +//! [/* leading comment of identifier */ a ]; +//! ``` +//! +//! ### Dangling Comments +//! +//! A comment that is neither at the start nor the end of a node +//! +//! ```ignore +//! [/* in between the brackets */ ]; +//! async /* between keywords */ function Test () {} +//! ``` +//! +//! ### Trailing Comments +//! +//! A comment at the end of a node +//! +//! ```ignore +//! [a /* trailing comment of a */, b, c]; +//! [ +//! a // trailing comment of a +//! ] +//! ``` +//! +//! ## Limitations +//! Limiting the placement of comments to leading, dangling, or trailing node comments reduces complexity inside the formatter but means, that the formatter's possibility of where comments can be formatted depends on the AST structure. +//! +//! For example, the continue statement in JavaScript is defined as: +//! +//! ```ungram +//! JsContinueStatement = +//! 'continue' +//! (label: 'ident')? +//! ';'? +//! ``` +//! +//! but a programmer may decide to add a comment in front or after the label: +//! +//! ```ignore +//! continue /* comment 1 */ label; +//! continue label /* comment 2*/; /* trailing */ +//! ``` +//! +//! Because all children of the `continue` statement are tokens, it is only possible to make the comments leading, dangling, or trailing comments of the `continue` statement. But this results in a loss of information as the formatting code can no longer distinguish if a comment appeared before or after the label and, thus, has to format them the same way. +//! +//! This hasn't shown to be a significant limitation today but the infrastructure could be extended to support a `label` on [`SourceComment`] that allows to further categorise comments. +//! + +mod builder; +mod map; + +use self::{builder::CommentsBuilderVisitor, map::CommentsMap}; +use crate::{TextSize, TransformSourceMap}; +use rome_rowan::syntax::SyntaxElementKey; +use rome_rowan::{Language, SyntaxNode, SyntaxToken, SyntaxTriviaPieceComments}; +use rustc_hash::FxHashSet; #[cfg(debug_assertions)] use std::cell::RefCell; -use std::collections::HashSet; use std::rc::Rc; #[derive(Copy, Clone, Eq, PartialEq, Debug)] @@ -13,9 +93,7 @@ pub enum CommentKind { /// /// ## Examples /// - /// ### JavaScript: - /// - /// ```javascript + /// ```ignore /// a /* test */ /// ``` InlineBlock, @@ -24,8 +102,6 @@ pub enum CommentKind { /// /// ## Examples /// - /// ### JavaScript - /// /// ```javascript /// /* first line /// * more content on the second line @@ -37,111 +113,660 @@ pub enum CommentKind { /// /// ## Examples /// - /// ### JavaScript - /// - /// ```javascript + /// ```ignore /// a // test /// ``` Line, } +impl CommentKind { + pub const fn is_line(&self) -> bool { + matches!(self, CommentKind::Line) + } + + pub const fn is_block(&self) -> bool { + matches!(self, CommentKind::Block) + } + + pub const fn is_inline_block(&self) -> bool { + matches!(self, CommentKind::InlineBlock) + } + + /// Returns `true` for comments that can appear inline between any two tokens. + /// + /// ## Examples + /// + /// ```rust + /// use rome_formatter::comments::CommentKind; + /// + /// // Block and InlineBlock comments can appear inline + /// assert!(CommentKind::Block.is_inline()); + /// assert!(CommentKind::InlineBlock.is_inline()); + /// + /// // But not line comments + /// assert!(!CommentKind::Line.is_inline()) + /// ``` + pub const fn is_inline(&self) -> bool { + matches!(self, CommentKind::InlineBlock | CommentKind::Block) + } +} + +/// A comment in the source document. #[derive(Debug, Clone)] pub struct SourceComment { /// The number of lines appearing before this comment - lines_before: u32, + pub(crate) lines_before: u32, + + pub(crate) lines_after: u32, /// The comment piece - piece: SyntaxTriviaPieceComments, + pub(crate) piece: SyntaxTriviaPieceComments, + + /// The kind of the comment. + pub(crate) kind: CommentKind, } impl SourceComment { - /// Creates a new trailing comment. A trailing comment always has 0 lines before. - pub fn trailing(piece: SyntaxTriviaPieceComments) -> Self { - Self { - lines_before: 0, - piece, - } + /// Returns the underlining comment trivia piece + pub fn piece(&self) -> &SyntaxTriviaPieceComments { + &self.piece } - /// Creates a leading comment with the specified lines before - pub fn leading(piece: SyntaxTriviaPieceComments, lines_before: u32) -> Self { - Self { - lines_before, - piece, - } + /// The number of lines between this comment and the **previous** token or comment. + /// + /// # Examples + /// + /// ## Same line + /// + /// ```ignore + /// a // end of line + /// ``` + /// + /// Returns `0` because there's no line break between the token `a` and the comment. + /// + /// ## Own Line + /// + /// ```ignore + /// a; + /// + /// /* comment */ + /// ``` + /// + /// Returns `2` because there are two line breaks between the token `a` and the comment. + pub fn lines_before(&self) -> u32 { + self.lines_before } - /// Returns the underlining comment trivia piece + /// The number of line breaks right after this comment. + /// + /// # Examples + /// + /// ## End of line + /// + /// ```ignore + /// a; // comment + /// + /// b; + /// ``` + /// + /// Returns `2` because there are two line breaks between the comment and the token `b`. + /// + /// ## Same line + /// + /// ```ignore + /// a; + /// /* comment */ b; + /// ``` + /// + /// Returns `0` because there are no line breaks between the comment and the token `b`. + pub fn lines_after(&self) -> u32 { + self.lines_after + } + + /// The kind of the comment + pub fn kind(&self) -> CommentKind { + self.kind + } +} + +/// A comment decorated with additional information about its surrounding context in the source document. +/// +/// Used by [CommentStyle::place_comment] to determine if this should become a [leading](self#leading-comments), [dangling](self#dangling-comments), or [trailing](self#trailing-comments) comment. +#[derive(Debug, Clone)] +pub struct DecoratedComment { + enclosing: SyntaxNode, + preceding: Option>, + following: Option>, + following_token: Option>, + text_position: CommentTextPosition, + lines_before: u32, + lines_after: u32, + comment: SyntaxTriviaPieceComments, + kind: CommentKind, +} + +impl DecoratedComment { + /// The closest parent node that fully encloses the comment. + /// + /// A node encloses a comment when the comment is between two of its direct children (ignoring lists). + /// + /// # Examples + /// + /// ```ignore + /// [a, /* comment */ b] + /// ``` + /// + /// The enclosing node is the array expression and not the identifier `b` because + /// `a` and `b` are children of the array expression and `comment` is a comment between the two nodes. + pub fn enclosing_node(&self) -> &SyntaxNode { + &self.enclosing + } + + /// Returns the comment piece. pub fn piece(&self) -> &SyntaxTriviaPieceComments { - &self.piece + &self.comment } - /// Returns the number of lines before directly before this comment + /// Returns the node preceding the comment. + /// + /// The direct child node (ignoring lists) of the [`enclosing_node`](DecoratedComment::enclosing_node) that precedes this comment. + /// + /// Returns [None] if the [`enclosing_node`](DecoratedComment::enclosing_node) only consists of tokens or if + /// all preceding children of the [`enclosing_node`](DecoratedComment::enclosing_node) have been tokens. + /// + /// The Preceding node is guaranteed to be a sibling of [`following_node`](DecoratedComment::following_node). + /// + /// # Examples + /// + /// ## Preceding tokens only + /// + /// ```ignore + /// [/* comment */] + /// ``` + /// Returns [None] because the comment has no preceding node, only a preceding `[` token. + /// + /// ## Preceding node + /// + /// ```ignore + /// [a /* comment */, b] + /// ``` + /// + /// Returns `Some(a)` because `a` directly precedes the comment. + /// + /// ## Preceding token and node + /// + /// ```ignore + /// [a, /* comment */] + /// ``` + /// + /// Returns `Some(a)` because `a` is the preceding node of `comment`. The presence of the `,` token + /// doesn't change that. + pub fn preceding_node(&self) -> Option<&SyntaxNode> { + self.preceding.as_ref() + } + + /// Takes the [`preceding_node`](DecoratedComment::preceding_node) and replaces it with [None]. + fn take_preceding_node(&mut self) -> Option> { + self.preceding.take() + } + + /// Returns the node following the comment. + /// + /// The direct child node (ignoring lists) of the [`enclosing_node`](DecoratedComment::enclosing_node) that follows this comment. + /// + /// Returns [None] if the [`enclosing_node`](DecoratedComment::enclosing_node) only consists of tokens or if + /// all children children of the [`enclosing_node`](DecoratedComment::enclosing_node) following this comment are tokens. + /// + /// The following node is guaranteed to be a sibling of [`preceding_node`](DecoratedComment::preceding_node). + /// + /// # Examples + /// + /// ## Following tokens only + /// + /// ```ignore + /// [ /* comment */ ] + /// ``` + /// + /// Returns [None] because there's no node following the comment, only the `]` token. + /// + /// ## Following node + /// + /// ```ignore + /// [ /* comment */ a ] + /// ``` + /// + /// Returns `Some(a)` because `a` is the node directly following the comment. + /// + /// ## Following token and node + /// + /// ```ignore + /// async /* comment */ function test() {} + /// ``` + /// + /// Returns `Some(test)` because the `test` identifier is the first node following `comment`. + /// + /// ## Following parenthesized expression + /// + /// ```ignore + /// !( + /// a /* comment */ + /// ); + /// b + /// ``` + /// + /// Returns `None` because `comment` is enclosed inside the parenthesized expression and it has no children + /// following `/* comment */. + pub fn following_node(&self) -> Option<&SyntaxNode> { + self.following.as_ref() + } + + /// Takes the [`following_node`](DecoratedComment::following_node) and replaces it with [None]. + fn take_following_node(&mut self) -> Option> { + self.following.take() + } + + /// The number of line breaks between this comment and the **previous** token or comment. + /// + /// # Examples + /// + /// ## Same line + /// + /// ```ignore + /// a // end of line + /// ``` + /// + /// Returns `0` because there's no line break between the token `a` and the comment. + /// + /// ## Own Line + /// + /// ```ignore + /// a; + /// + /// /* comment */ + /// ``` + /// + /// Returns `2` because there are two line breaks between the token `a` and the comment. pub fn lines_before(&self) -> u32 { self.lines_before } + + /// The number of line breaks right after this comment. + /// + /// # Examples + /// + /// ## End of line + /// + /// ```ignore + /// a; // comment + /// + /// b; + /// ``` + /// + /// Returns `2` because there are two line breaks between the comment and the token `b`. + /// + /// ## Same line + /// + /// ```ignore + /// a; + /// /* comment */ b; + /// ``` + /// + /// Returns `0` because there are no line breaks between the comment and the token `b`. + pub fn lines_after(&self) -> u32 { + self.lines_after + } + + /// Returns the [CommentKind] of the comment. + pub fn kind(&self) -> CommentKind { + self.kind + } + + /// The position of the comment in the text. + pub fn text_position(&self) -> CommentTextPosition { + self.text_position + } + + /// The next token that comes after this comment. It is possible that other comments are between this comment + /// and the token. + /// + /// ```ignore + /// a /* comment */ /* other b */ + /// ``` + /// + /// The `following_token` for both comments is `b` because it's the token coming after the comments. + pub fn following_token(&self) -> Option<&SyntaxToken> { + self.following_token.as_ref() + } } -impl CommentKind { - pub const fn is_line(&self) -> bool { - matches!(self, CommentKind::Line) +impl From> for SourceComment { + fn from(decorated: DecoratedComment) -> Self { + Self { + lines_before: decorated.lines_before, + lines_after: decorated.lines_after, + piece: decorated.comment, + kind: decorated.kind, + } } +} - pub const fn is_block(&self) -> bool { - matches!(self, CommentKind::Block) +/// The position of a comment in the source text. +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum CommentTextPosition { + /// A comment that is on the same line as the preceding token and is separated by at least one line break from the following token. + /// + /// # Examples + /// + /// ## End of line + /// + /// ```ignore + /// a; /* this */ // or this + /// b; + /// ``` + /// + /// Both `/* this */` and `// or this` are end of line comments because both comments are separated by + /// at least one line break from the following token `b`. + /// + /// ## Own line + /// + /// ```ignore + /// a; + /// /* comment */ + /// b; + /// ``` + /// + /// This is not an end of line comment because it isn't on the same line as the preceding token `a`. + EndOfLine, + + /// A Comment that is separated by at least one line break from the preceding token. + /// + /// # Examples + /// + /// ```ignore + /// a; + /// /* comment */ /* or this */ + /// b; + /// ``` + /// + /// Both comments are own line comments because they are separated by one line break from the preceding + /// token `a`. + OwnLine, + + /// A comment that is placed on the same line as the preceding and following token. + /// + /// # Examples + /// + /// ```ignore + /// a /* comment */ + b + /// ``` + SameLine, +} + +impl CommentTextPosition { + pub const fn is_same_line(&self) -> bool { + matches!(self, CommentTextPosition::SameLine) } - pub const fn is_inline_block(&self) -> bool { - matches!(self, CommentKind::InlineBlock) + pub const fn is_own_line(&self) -> bool { + matches!(self, CommentTextPosition::OwnLine) } - /// Returns `true` for comments that can appear inline between any two tokens. + pub const fn is_end_of_line(&self) -> bool { + matches!(self, CommentTextPosition::EndOfLine) + } +} + +#[derive(Debug)] +pub enum CommentPlacement { + /// Makes `comment` a [leading comment](self#leading-comments) of `node`. + Leading { + node: SyntaxNode, + comment: SourceComment, + }, + /// Makes `comment` a [trailing comment](self#trailing-comments) of `node`. + Trailing { + node: SyntaxNode, + comment: SourceComment, + }, + + /// Makes `comment` a [dangling comment](self#dangling-comments) of `node`. + Dangling { + node: SyntaxNode, + comment: SourceComment, + }, + + /// Uses the default heuristic to determine the placement of the comment. + /// + /// # Same line comments + /// + /// Makes the comment a... + /// + /// * [trailing comment] of the [`preceding_node`] if both the [`following_node`] and [`preceding_node`] are not [None] + /// and the comment and [`preceding_node`] are only separated by a space (there's no token between the comment and [`preceding_node`]). + /// * [leading comment] of the [`following_node`] if the [`following_node`] is not [None] + /// * [trailing comment] of the [`preceding_node`] if the [`preceding_node`] is not [None] + /// * [dangling comment] of the [`enclosing_node`]. /// /// ## Examples + /// ### Comment with preceding and following nodes /// - /// ```rust - /// use rome_formatter::CommentKind; + /// ```ignore + /// [ + /// a, // comment + /// b + /// ] + /// ``` /// - /// // Block and InlineBlock comments can appear inline - /// assert!(CommentKind::Block.is_inline()); - /// assert!(CommentKind::InlineBlock.is_inline()); + /// The comment becomes a [trailing comment] of the node `a`. /// - /// // But not line comments - /// assert!(!CommentKind::Line.is_inline()) + /// ### Comment with preceding node only + /// + /// ```ignore + /// [ + /// a // comment + /// ] /// ``` - pub const fn is_inline(&self) -> bool { - matches!(self, CommentKind::InlineBlock | CommentKind::Block) + /// + /// The comment becomes a [trailing comment] of the node `a`. + /// + /// ### Comment with following node only + /// + /// ```ignore + /// [ // comment + /// b + /// ] + /// ``` + /// + /// The comment becomes a [leading comment] of the node `b`. + /// + /// ### Dangling comment + /// + /// ```ignore + /// [ // comment + /// ] + /// ``` + /// + /// The comment becomes a [dangling comment] of the enclosing array expression because both the [`preceding_node`] and [`following_node`] are [None]. + /// + /// # Own line comments + /// + /// Makes the comment a... + /// + /// * [leading comment] of the [`following_node`] if the [`following_node`] is not [None] + /// * or a [trailing comment] of the [`preceding_node`] if the [`preceding_node`] is not [None] + /// * or a [dangling comment] of the [`enclosing_node`]. + /// + /// ## Examples + /// + /// ### Comment with leading and preceding nodes + /// + /// ```ignore + /// [ + /// a, + /// // comment + /// b + /// ] + /// ``` + /// + /// The comment becomes a [leading comment] of the node `b`. + /// + /// ### Comment with preceding node only + /// + /// ```ignore + /// [ + /// a + /// // comment + /// ] + /// ``` + /// + /// The comment becomes a [trailing comment] of the node `a`. + /// + /// ### Comment with following node only + /// + /// ```ignore + /// [ + /// // comment + /// b + /// ] + /// ``` + /// + /// The comment becomes a [leading comment] of the node `b`. + /// + /// ### Dangling comment + /// + /// ```ignore + /// [ + /// // comment + /// ] + /// ``` + /// + /// The comment becomes a [dangling comment] of the array expression because both [`preceding_node`] and [`following_node`] are [None]. + /// + /// + /// # End of line comments + /// Makes the comment a... + /// + /// * [trailing comment] of the [`preceding_node`] if the [`preceding_node`] is not [None] + /// * or a [leading comment] of the [`following_node`] if the [`following_node`] is not [None] + /// * or a [dangling comment] of the [`enclosing_node`]. + /// + /// + /// ## Examples + /// + /// ### Comment with leading and preceding nodes + /// + /// ```ignore + /// [a /* comment */, b] + /// ``` + /// + /// The comment becomes a [trailing comment] of the node `a` because there's no token between the node `a` and the `comment`. + /// + /// ```ignore + /// [a, /* comment */ b] + /// ``` + /// + /// The comment becomes a [leading comment] of the node `b` because the node `a` and the comment are separated by a `,` token. + /// + /// ### Comment with preceding node only + /// + /// ```ignore + /// [a, /* last */ ] + /// ``` + /// + /// The comment becomes a [trailing comment] of the node `a` because the [`following_node`] is [None]. + /// + /// ### Comment with following node only + /// + /// ```ignore + /// [/* comment */ b] + /// ``` + /// + /// The comment becomes a [leading comment] of the node `b` because the [`preceding_node`] is [None] + /// + /// ### Dangling comment + /// + /// ```ignore + /// [/* comment*/] + /// ``` + /// + /// The comment becomes a [dangling comment] of the array expression because both [`preceding_node`] and [`following_node`] are [None]. + /// + /// [`preceding_node`]: DecoratedComment::preceding_node + /// [`following_node`]: DecoratedComment::following_node + /// [`enclosing_node`]: DecoratedComment::enclosing_node + /// [trailing comment]: self#trailing-comments + /// [leading comment]: self#leading-comments + /// [dangling comment]: self#dangling-comments + Default(DecoratedComment), +} + +impl CommentPlacement { + /// Makes `comment` a [leading comment](self#leading-comments) of `node`. + #[inline] + pub fn leading(node: SyntaxNode, comment: impl Into>) -> Self { + Self::Leading { + node, + comment: comment.into(), + } + } + + /// Makes `comment` a [dangling comment](self::dangling-comments) of `node`. + pub fn dangling(node: SyntaxNode, comment: impl Into>) -> Self { + Self::Dangling { + node, + comment: comment.into(), + } + } + + /// Makes `comment` a [trailing comment](self::trailing-comments) of `node`. + #[inline] + pub fn trailing(node: SyntaxNode, comment: impl Into>) -> Self { + Self::Trailing { + node, + comment: comment.into(), + } + } + + /// Returns the placement if it isn't [CommentPlacement::Default], otherwise calls `f` and returns the result. + #[inline] + pub fn or_else(self, f: F) -> Self + where + F: FnOnce(DecoratedComment) -> CommentPlacement, + { + match self { + CommentPlacement::Default(comment) => f(comment), + placement => placement, + } } } /// Defines how to format comments for a specific [Language]. -pub trait CommentStyle { +pub trait CommentStyle: Default { + type Language: Language; + /// Returns `true` if a comment with the given `text` is a `rome-ignore format:` suppression comment. - fn is_suppression(&self, text: &str) -> bool; + fn is_suppression(_text: &str) -> bool { + false + } /// Returns the (kind)[CommentKind] of the comment - fn get_comment_kind(&self, comment: &SyntaxTriviaPieceComments) -> CommentKind; - - /// Returns `true` if a token with the passed `kind` marks the start of a group. Common group tokens are: - /// * left parentheses: `(`, `[`, `{` - fn is_group_start_token(&self, kind: L::Kind) -> bool; - - /// Returns `true` if a token with the passed `kind` marks the end of a group. Common group end tokens are: - /// * right parentheses: `)`, `]`, `}` - /// * end of statement token: `;` - /// * element separator: `,` or `.`. - /// * end of file token: `EOF` - fn is_group_end_token(&self, kind: L::Kind) -> bool; + fn get_comment_kind(comment: &SyntaxTriviaPieceComments) -> CommentKind; + + /// Determines the placement of `comment`. + /// + /// The default implementation returns [CommentPlacement::Default]. + fn place_comment( + &self, + comment: DecoratedComment, + ) -> CommentPlacement { + CommentPlacement::Default(comment) + } } -/// Type that stores the comments of a tree and gives access to: -/// -/// * whether a node should be formatted as is because it has a leading suppression comment. -/// * a node's leading and trailing comments -/// * the dangling comments of a token +/// The comments of a syntax tree stored by node. /// /// Cloning `comments` is cheap as it only involves bumping a reference counter. -#[derive(Debug, Default, Clone)] +#[derive(Debug, Clone, Default)] pub struct Comments { /// The use of a [Rc] is necessary to achieve that [Comments] has a lifetime that is independent from the [crate::Formatter]. /// Having independent lifetimes is necessary to support the use case where a (formattable object)[crate::Format] @@ -162,67 +787,113 @@ pub struct Comments { } impl Comments { - /// Extracts all the suppressions from `root` and its child nodes. - pub fn from_node(root: &SyntaxNode, language: &FormatLanguage) -> Self + /// Extracts all the comments from `root` and its descendants nodes. + pub fn from_node -; - -// this should remain as-is -
- {/* prettier-ignore */} - -
; - -// this should remain as-is -f( - - {/*prettier-ignore*/} - - -); - -// this be formatted -
- {/* prettier-ignore */} foo - -
; - -// this should remain as-is -
-{ - /* prettier-ignore */ - foo ( ) -} -
; - -// this should remain as-is -
-{ - /* prettier-ignore */ - x ? : -} -
; - -push( - // prettier-ignore - :) - , -); - -function f() { - // rome-ignore format: Instability issue - return ( - // prettier-ignore - /* $FlowFixMe(>=0.53.0) */ - - ); -} -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,20 +1,22 @@ - // this should remain as-is -
- {/* prettier-ignore */} -- -+ -
; - - // this should remain as-is -
- {/* prettier-ignore */} -- -+ -
; - - // this should remain as-is - f( - - {/*prettier-ignore*/} -- -+ - , - ); - -@@ -28,16 +30,15 @@ -
- { - /* prettier-ignore */ -- foo ( ) -+ foo ( ) - } -
; - - // this should remain as-is -
- { -- /* prettier-ignore */ -- x ? : -- } -+ /* prettier-ignore */ -+ x ? : } -
; - - push( -@@ -47,6 +48,7 @@ - ); - - function f() { -+ // rome-ignore format: Instability issue - return ( - // prettier-ignore - /* $FlowFixMe(>=0.53.0) */ -``` - -# Output - -```js -// this should remain as-is -
- {/* prettier-ignore */} - -
; - -// this should remain as-is -
- {/* prettier-ignore */} - -
; - -// this should remain as-is -f( - - {/*prettier-ignore*/} - - , -); - -// this be formatted -
- {/* prettier-ignore */} foo - -
; - -// this should remain as-is -
- { - /* prettier-ignore */ - foo ( ) - } -
; - -// this should remain as-is -
- { - /* prettier-ignore */ - x ? : } -
; - -push( - // prettier-ignore - :) - , -); - -function f() { - // rome-ignore format: Instability issue - return ( - // prettier-ignore - /* $FlowFixMe(>=0.53.0) */ - - ); -} -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/jsx/split-attrs/test.js b/crates/rome_js_formatter/tests/specs/prettier/jsx/split-attrs/test.js index 59f3a7a8ae1..4ae4a5d6565 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/jsx/split-attrs/test.js +++ b/crates/rome_js_formatter/tests/specs/prettier/jsx/split-attrs/test.js @@ -44,6 +44,5 @@ long_string = long_string_with_extra_param =
hello world
-// rome-ignore format: Instability issue long_obj =
hello world
diff --git a/crates/rome_js_formatter/tests/specs/prettier/jsx/split-attrs/test.js.snap b/crates/rome_js_formatter/tests/specs/prettier/jsx/split-attrs/test.js.snap deleted file mode 100644 index 9042378ed7f..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/jsx/split-attrs/test.js.snap +++ /dev/null @@ -1,261 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs -info: - test_file: jsx/split-attrs/test.js ---- - -# Input - -```js -long_closed = - - -long_open = - - hello - - -long_open_long_children = - - - Hello world - -
hey hiya how are ya
-
-
-
-
- d - - - -short_closed = - - -short_open = - - hello - - -make_self_closing = -
- - - -
- -leave_opening = - - -long_string = -
hello world
- -long_string_with_extra_param = -
hello world
- -// rome-ignore format: Instability issue -long_obj = -
hello world
-``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -155,16 +155,6 @@ -
- ); - --long_obj = ( --
-- hello world --
--); -+// rome-ignore format: Instability issue -+long_obj = -+
hello world
-``` - -# Output - -```js -long_closed = ( - -); - -long_open = ( - - hello - -); - -long_open_long_children = ( - - - Hello world - -
-
-
-
-
-
hey hiya how are ya
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - - d - - - - - -); - -short_closed = ; - -short_open = ( - - hello - -); - -make_self_closing = ( -
- - -
-); - -leave_opening = ( - - {" "} - -); - -long_string = ( -
- hello world -
-); - -long_string_with_extra_param = ( -
- hello world -
-); - -// rome-ignore format: Instability issue -long_obj = -
hello world
-``` - - -# Lines exceeding max width of 80 characters -``` - 144:
- 151: className="i use bootstrap and just put loooaads of classnames in here all the time" - 160:
hello world
-``` - diff --git a/crates/rome_js_formatter/tests/specs/prettier/jsx/spread/attribute.js.snap b/crates/rome_js_formatter/tests/specs/prettier/jsx/spread/attribute.js.snap index 39071cb7e1f..179fb709d7c 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/jsx/spread/attribute.js.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/jsx/spread/attribute.js.snap @@ -40,40 +40,33 @@ info: ```diff --- Prettier +++ Rome -@@ -9,28 +9,21 @@ -
; +@@ -6,7 +6,7 @@ -
; +
; + +-
; ++
;
; + { +@@ -23,14 +23,14 @@
;
; ``` @@ -88,26 +81,33 @@ info:
; -
; +
;
;
;
;
; ``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/jsx/spread/child.js b/crates/rome_js_formatter/tests/specs/prettier/jsx/spread/child.js index 94e59bf6d24..c8798b1e0d2 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/jsx/spread/child.js +++ b/crates/rome_js_formatter/tests/specs/prettier/jsx/spread/child.js @@ -4,7 +4,6 @@
{/* comment */...a}
; -// rome-ignore format: Instability issue
{...a //comment }
; @@ -17,7 +16,6 @@ ...a }
; -// rome-ignore format: Instability issue
{//comment ...a // comment }
; diff --git a/crates/rome_js_formatter/tests/specs/prettier/jsx/spread/child.js.snap b/crates/rome_js_formatter/tests/specs/prettier/jsx/spread/child.js.snap index 5358e69534a..c07cc5252c9 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/jsx/spread/child.js.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/jsx/spread/child.js.snap @@ -13,7 +13,6 @@ info:
{/* comment */...a}
; -// rome-ignore format: Instability issue
{...a //comment }
; @@ -26,7 +25,6 @@ info: ...a }
; -// rome-ignore format: Instability issue
{//comment ...a // comment }
; @@ -38,47 +36,34 @@ info: ```diff --- Prettier +++ Rome -@@ -4,29 +4,23 @@ +@@ -2,7 +2,7 @@ -
{/* comment */ ...a}
; +
{...a /* comment */}
; --
-- { -- ...a //comment -- } --
; -+// rome-ignore format: Instability issue -+
{...a //comment -+}
; +-
{/* comment */ ...a}
; ++
{.../* comment */ a}
;
-- { -- ...a -- //comment -+ {...a -+ //comment - } -
; + { +@@ -19,14 +19,14 @@
{ - //comment - ...a -- } -+ //comment -+ ...a} ++ ...//comment ++ a + }
; --
-- { +
+ { - //comment - ...a // comment -- } --
; -+// rome-ignore format: Instability issue -+
{//comment -+ ...a // comment -+}
; ++ ...//comment ++ a // comment + } +
; ``` # Output @@ -88,28 +73,34 @@ info:
{...a /* comment */}
; -
{/* comment */ ...a}
; +
{.../* comment */ a}
; -// rome-ignore format: Instability issue -
{...a //comment -}
; +
+ { + ...a //comment + } +
;
- {...a - //comment + { + ...a + //comment }
;
{ - //comment - ...a} + ...//comment + a + }
; -// rome-ignore format: Instability issue -
{//comment - ...a // comment -}
; +
+ { + ...//comment + a // comment + } +
; ``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/arrow/comments.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/arrow/comments.ts.snap index fad26202e0f..14d52ed8780 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/arrow/comments.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/arrow/comments.ts.snap @@ -23,7 +23,7 @@ const fn2 = () => { ```diff --- Prettier +++ Rome -@@ -1,9 +1,9 @@ +@@ -1,6 +1,6 @@ const fn1 = () => { return; -}; /* foo */ @@ -31,11 +31,6 @@ const fn2 = () => { const fn2 = () => { return; --}; -- -+} - // foo -+; ``` # Output @@ -47,9 +42,9 @@ const fn1 = () => { const fn2 = () => { return; -} +}; + // foo -; ``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/class-comment/class-implements.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/class-comment/class-implements.ts.snap deleted file mode 100644 index 879d379e679..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/class-comment/class-implements.ts.snap +++ /dev/null @@ -1,271 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -class a1 extends b // comment -implements z -{ - constructor() {} -} - -class a2 extends b implements z { // comment - constructor() {} -} - -class a3 extends b -implements -// comment -z, -y { - constructor() {} -} - -class a4 extends b -implements z, // comment -y { - constructor() {} -} - -class a5 extends b implements - z, // comment-z - y // comment-y - { - constructor() {} -} - -class a6 extends b implements -// comment-z1 - z, // comment-z2 - // comment-y1 - y // comment-y2 - { - constructor() {} -} - -class a7 extends b implements -// comment-z1 - z, // comment-z2 - // comment-y1 - y // comment-y2 - // comment-y3 - { - //comment-body - constructor() {} -} - -class a8 extends b // comment-b - implements -// comment-z1 - z, // comment-z2 - // comment-y1 - y // comment-y2 - { - constructor() {} -} - -class a9 extends -// comment-b1 -b // comment-b2 -// comment-b3 - implements -// comment-z1 - z, // comment-z2 - // comment-y1 - y // comment-y2 - { - constructor() {} -} -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -12,8 +12,10 @@ - - class a3 - extends b -- // comment -- implements z, y -+ implements -+ // comment -+ z, -+ y - { - constructor() {} - } -@@ -31,60 +33,56 @@ - extends b - implements - z, // comment-z -- y -+ y // comment-y - { -- // comment-y - constructor() {} - } - - class a6 - extends b -- // comment-z1 - implements -+ // comment-z1 - z, // comment-z2 - // comment-y1 -- y -+ y // comment-y2 - { -- // comment-y2 - constructor() {} - } - - class a7 - extends b -- // comment-z1 - implements -+ // comment-z1 - z, // comment-z2 - // comment-y1 -- y -+ y // comment-y2 -+// comment-y3 - { -- // comment-y2 -- // comment-y3 - //comment-body - constructor() {} - } - - class a8 - extends b // comment-b -- // comment-z1 - implements -+ // comment-z1 - z, // comment-z2 - // comment-y1 -- y -+ y // comment-y2 - { -- // comment-y2 - constructor() {} - } - - class a9 -+ extends - // comment-b1 -- extends b // comment-b2 -+ b // comment-b2 - // comment-b3 -- // comment-z1 - implements -+ // comment-z1 - z, // comment-z2 - // comment-y1 -- y -+ y // comment-y2 - { -- // comment-y2 - constructor() {} - } -``` - -# Output - -```js -class a1 - extends b // comment - implements z -{ - constructor() {} -} - -class a2 extends b implements z { - // comment - constructor() {} -} - -class a3 - extends b - implements - // comment - z, - y -{ - constructor() {} -} - -class a4 - extends b - implements - z, // comment - y -{ - constructor() {} -} - -class a5 - extends b - implements - z, // comment-z - y // comment-y -{ - constructor() {} -} - -class a6 - extends b - implements - // comment-z1 - z, // comment-z2 - // comment-y1 - y // comment-y2 -{ - constructor() {} -} - -class a7 - extends b - implements - // comment-z1 - z, // comment-z2 - // comment-y1 - y // comment-y2 -// comment-y3 -{ - //comment-body - constructor() {} -} - -class a8 - extends b // comment-b - implements - // comment-z1 - z, // comment-z2 - // comment-y1 - y // comment-y2 -{ - constructor() {} -} - -class a9 - extends - // comment-b1 - b // comment-b2 - // comment-b3 - implements - // comment-z1 - z, // comment-z2 - // comment-y1 - y // comment-y2 -{ - constructor() {} -} -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/class-comment/declare.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/class-comment/declare.ts.snap deleted file mode 100644 index 41c46755a99..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/class-comment/declare.ts.snap +++ /dev/null @@ -1,65 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -declare class a // 1 - // extends b // 2 - implements z,x // 3 -{ - doo:boolean -} - -declare class A1 // 1 -// 2 -extends B // 3 -{} -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,13 +1,12 @@ - declare class a // 1 - // extends b // 2 -- implements z, x -+ implements -+ z, -+ x // 3 - { -- // 3 - doo: boolean; - } - - declare class A1 // 1 - // 2 -- extends B { -- // 3 --} -+ extends B {} // 3 -``` - -# Output - -```js -declare class a // 1 - // extends b // 2 - implements - z, - x // 3 -{ - doo: boolean; -} - -declare class A1 // 1 - // 2 - extends B {} // 3 -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/class/extends_implements.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/class/extends_implements.ts.snap deleted file mode 100644 index a7cc4ca8777..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/class/extends_implements.ts.snap +++ /dev/null @@ -1,188 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -class Class extends AbstractClass implements Interface1, Interface2, Interface3, Interface4 {} - -class ExtendsAbstractClassAndImplementsInterfaces1 extends AbstractClass - implements Interface1, Interface2, Interface3, Interface4 {} - -class ExtendsAbstractClassAndImplementsInterfaces2 - extends AAAAAAAAAAAAAAbstractClass - implements Interface1, Interface2, Interface3, Interface4 {} - -class ExtendsAbstractClassAndImplementsInterfaces3 - extends AAAAAAAAAAAAAAbstractClass - implements - Interface1, - Interface2, - Interface3, - Interface4, - Interface5, - Interface6, - Interface7, - Interface8 {} - -class ExtendsAbstractClassAndImplementsInterfaces4 - extends AAAAAAAAAAAAAAbstractClass {} - -class ExtendsAbstractClassAndImplementsInterfaces5 - extends AAAAAAAAAAAAAAbstractClass - implements - Interface1, - Interface2, - Interface3, - Interface4, - Interface5, - Interface6, - Interface7, - Interface8 {} - -class ImplementsInterfaceAndExtendsAbstractClass1 - extends FOOOOOOOOOOOOOOOOO - implements FOOOOOOOOOOOOOOOOO, BARRRRRRRRRR {} - -class Foo implements Foo {} - -class ImplementsInterfaceAndExtendsAbstractClass2< - TypeArgumentNumberOne, - TypeArgumentNumberTwo, - TypeArgumentNumberThree - > - extends FOOOOOOOOOOOOOOOOOO implements BaseInterface {} - -class ImplementsInterfaceClass1< - TypeArgumentNumberOne, - TypeArgumentNumberTwo, - TypeArgumentNumberThree - > - implements BaseInterface {} - -class ImplementsInterfaceClassWithComments1< - TypeArgumentNumberOne, - TypeArgumentNumberTwo, - TypeArgumentNumberThree - > // comments - implements BaseInterface {} -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -68,10 +68,11 @@ - implements BaseInterface {} - - class ImplementsInterfaceClass1< -- TypeArgumentNumberOne, -- TypeArgumentNumberTwo, -- TypeArgumentNumberThree, --> implements BaseInterface {} -+ TypeArgumentNumberOne, -+ TypeArgumentNumberTwo, -+ TypeArgumentNumberThree, -+ > -+ implements BaseInterface {} - - class ImplementsInterfaceClassWithComments1< - TypeArgumentNumberOne, -``` - -# Output - -```js -class Class - extends AbstractClass - implements Interface1, Interface2, Interface3, Interface4 {} - -class ExtendsAbstractClassAndImplementsInterfaces1 - extends AbstractClass - implements Interface1, Interface2, Interface3, Interface4 {} - -class ExtendsAbstractClassAndImplementsInterfaces2 - extends AAAAAAAAAAAAAAbstractClass - implements Interface1, Interface2, Interface3, Interface4 {} - -class ExtendsAbstractClassAndImplementsInterfaces3 - extends AAAAAAAAAAAAAAbstractClass - implements - Interface1, - Interface2, - Interface3, - Interface4, - Interface5, - Interface6, - Interface7, - Interface8 {} - -class ExtendsAbstractClassAndImplementsInterfaces4 extends AAAAAAAAAAAAAAbstractClass< - Type1, - Type2, - Type3, - Type4, - Type5, - Type6, - Type7 -> {} - -class ExtendsAbstractClassAndImplementsInterfaces5 - extends AAAAAAAAAAAAAAbstractClass< - Type1, - Type2, - Type3, - Type4, - Type5, - Type6, - Type7 - > - implements - Interface1, - Interface2, - Interface3, - Interface4, - Interface5, - Interface6, - Interface7, - Interface8 {} - -class ImplementsInterfaceAndExtendsAbstractClass1 - extends FOOOOOOOOOOOOOOOOO - implements FOOOOOOOOOOOOOOOOO, BARRRRRRRRRR {} - -class Foo - implements Foo {} - -class ImplementsInterfaceAndExtendsAbstractClass2< - TypeArgumentNumberOne, - TypeArgumentNumberTwo, - TypeArgumentNumberThree, - > - extends FOOOOOOOOOOOOOOOOOO - implements BaseInterface {} - -class ImplementsInterfaceClass1< - TypeArgumentNumberOne, - TypeArgumentNumberTwo, - TypeArgumentNumberThree, - > - implements BaseInterface {} - -class ImplementsInterfaceClassWithComments1< - TypeArgumentNumberOne, - TypeArgumentNumberTwo, - TypeArgumentNumberThree, - > // comments - implements BaseInterface {} -``` - - -# Lines exceeding max width of 80 characters -``` - 25: class ExtendsAbstractClassAndImplementsInterfaces4 extends AAAAAAAAAAAAAAbstractClass< -``` - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/class/generics.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/class/generics.ts.snap deleted file mode 100644 index d91ddcf9d4d..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/class/generics.ts.snap +++ /dev/null @@ -1,52 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -class implements Map {} - -interface AudioBufferList { - mBuffers: interop.Reference; -} -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,5 +1,5 @@ - class implements Map {} - - interface AudioBufferList { -- mBuffers: interop.Reference; -+ mBuffers: interop.Reference; - } -``` - -# Output - -```js -class implements Map {} - -interface AudioBufferList { - mBuffers: interop.Reference; -} -``` - - -# Errors -``` -error[SyntaxError]: class declarations must have a name - ┌─ generics.ts:1:1 - │ -1 │ class implements Map {} - │ ^^^^^ - - -``` - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/after_jsx_generic.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/after_jsx_generic.ts.snap deleted file mode 100644 index 36413b8d1b1..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/after_jsx_generic.ts.snap +++ /dev/null @@ -1,93 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -let comp = ( - <> - /* comment1 */> - foo /* comment2 */> - /* comment3 */ bar> - foo /* comment4 */ bar> - - - // comment5 - > - - foo - // comment6 - > - - // comment7 - foo - > - - foo - // comment8 - bar - > - -); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,7 +1,7 @@ - let comp = ( - <> -- /* comment1 */> -- foo /* comment2 */> -+ /* comment1 */ > -+ foo /* comment2 */ > - /* comment3 */ bar> - foo /* comment4 */ bar> - -@@ -10,7 +10,7 @@ - > - - foo -- // comment6 -+ // comment6 - > - - // comment7 -``` - -# Output - -```js -let comp = ( - <> - /* comment1 */ > - foo /* comment2 */ > - /* comment3 */ bar> - foo /* comment4 */ bar> - - - // comment5 - > - - foo - // comment6 - > - - // comment7 - foo - > - - foo - // comment8 - bar - > - -); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/mapped_types.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/mapped_types.ts.snap index 3ab2cc6ed58..9cdf5d2b939 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/mapped_types.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/mapped_types.ts.snap @@ -1,5 +1,7 @@ --- source: crates/rome_js_formatter/tests/prettier_tests.rs +info: + test_file: typescript/comments/mapped_types.ts --- # Input @@ -53,7 +55,7 @@ type M = { [m in M] /* commentG */: string } ```diff --- Prettier +++ Rome -@@ -24,17 +24,30 @@ +@@ -24,7 +24,7 @@ }; type G = { @@ -61,36 +63,13 @@ type M = { [m in M] /* commentG */: string } + [g in G] /* commentG */ : string; }; --type H = { [/* commentH */ h in H]: string }; -+type H = { -+ /* commentH */ -+ [h in H]: string; -+}; + type H = { [/* commentH */ h in H]: string }; +@@ -37,4 +37,4 @@ --type I = { [/* commentI */ i in I]: string }; -+type I = { -+ [/* commentI */ i in I]: string; -+}; - --type J = { [j /* commentJ */ in J]: string }; -+type J = { -+ [j /* commentJ */ in J]: string; -+}; - --type K = { [k in /* commentK */ K]: string }; -+type K = { -+ [k in /* commentK */ K]: string; -+}; - --type L = { [l in L /* commentL */]: string }; -+type L = { -+ [l in L /* commentL */]: string; -+}; + type L = { [l in L /* commentL */]: string }; -type M = { [m in M /* commentG */]: string }; -+type M = { -+ [m in M] /* commentG */ : string; -+}; ++type M = { [m in M] /* commentG */ : string }; ``` # Output @@ -125,30 +104,17 @@ type G = { [g in G] /* commentG */ : string; }; -type H = { - /* commentH */ - [h in H]: string; -}; +type H = { [/* commentH */ h in H]: string }; -type I = { - [/* commentI */ i in I]: string; -}; +type I = { [/* commentI */ i in I]: string }; -type J = { - [j /* commentJ */ in J]: string; -}; +type J = { [j /* commentJ */ in J]: string }; -type K = { - [k in /* commentK */ K]: string; -}; +type K = { [k in /* commentK */ K]: string }; -type L = { - [l in L /* commentL */]: string; -}; +type L = { [l in L /* commentL */]: string }; -type M = { - [m in M] /* commentG */ : string; -}; +type M = { [m in M] /* commentG */ : string }; ``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/method_types.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/method_types.ts.snap index 458914df22c..e5a94a3b79d 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/method_types.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/method_types.ts.snap @@ -1,5 +1,7 @@ --- source: crates/rome_js_formatter/tests/prettier_tests.rs +info: + test_file: typescript/comments/method_types.ts --- # Input @@ -52,25 +54,21 @@ abstract class Test { ```diff --- Prettier +++ Rome -@@ -1,11 +1,13 @@ +@@ -1,11 +1,11 @@ interface foo1 { -- bar3 /* foo */(/* baz */); // bat + bar3 /* foo */(/* baz */); // bat - bar /* foo */ /* bar */?(/* baz */) /* bat */; -- bar2 /* foo */(/* baz */) /* bat */; -+ bar3 /* foo */ ( -+ /* baz */ -+ ); // bat -+ bar /* foo */ ? /* bar */ (/* baz */) /* bat */; -+ bar2 /* foo */ (/* baz */) /* bat */; ++ bar /* foo */?/* bar */ (/* baz */) /* bat */; + bar2 /* foo */(/* baz */) /* bat */; } interface foo2 { - bar /* foo */?(/* bar */ bar: /* baz */ string): /* bat */ string; -+ bar /* foo */ ? /* bar */ (bar: /* baz */ string): /* bat */ string; ++ bar /* foo */?/* bar */ (bar: /* baz */ string): /* bat */ string; } interface foo3 { -@@ -17,23 +19,23 @@ +@@ -17,20 +17,20 @@ } interface foo5 { @@ -96,27 +94,20 @@ abstract class Test { +let foo10: new /* foo */ (a: /* bar */ string) /* baz */ => string; abstract class Test { -- abstract foo12 /* foo */(a: /* bar */ string): /* baz */ void; -+ abstract foo12 /* foo */ (a: /* bar */ string): /* baz */ void; - -- abstract foo13 /* foo */(/* bar */); /* baz */ -+ abstract foo13 /* foo */ (/* bar */) /* baz */; - } + abstract foo12 /* foo */(a: /* bar */ string): /* baz */ void; ``` # Output ```js interface foo1 { - bar3 /* foo */ ( - /* baz */ - ); // bat - bar /* foo */ ? /* bar */ (/* baz */) /* bat */; - bar2 /* foo */ (/* baz */) /* bat */; + bar3 /* foo */(/* baz */); // bat + bar /* foo */?/* bar */ (/* baz */) /* bat */; + bar2 /* foo */(/* baz */) /* bat */; } interface foo2 { - bar /* foo */ ? /* bar */ (bar: /* baz */ string): /* bat */ string; + bar /* foo */?/* bar */ (bar: /* baz */ string): /* bat */ string; } interface foo3 { @@ -144,9 +135,9 @@ let foo9: new /* foo */ (/* bar */) /* baz */ => string; let foo10: new /* foo */ (a: /* bar */ string) /* baz */ => string; abstract class Test { - abstract foo12 /* foo */ (a: /* bar */ string): /* baz */ void; + abstract foo12 /* foo */(a: /* bar */ string): /* baz */ void; - abstract foo13 /* foo */ (/* bar */) /* baz */; + abstract foo13 /* foo */(/* bar */); /* baz */ } ``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/methods.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/methods.ts.snap deleted file mode 100644 index 198dd71b9bf..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/methods.ts.snap +++ /dev/null @@ -1,131 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -export class Point { -/** - * Does something. - */ - foo() {} - - /** - * Does something else. - */ - bar() {} - - /** - * Does - * something - * much - * better - * than - * the - * rest. - */ - baz() {} - - /** - * Buzz-Fizz. - * Note: This is indented too far. - */ - fizzBuzz() {} - - /** - * Turns the given string into pig-latin. - */ - pigLatinize(value: string) { -/** - * This is a block comment inside of a method. - */ - } - - /** - * One - * Two - * Three -* Four - */ - mismatchedIndentation() {} - - inline /* foo*/ (/* bar */) /* baz */ {} - - noBody(/* comment */ arg); -} -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -43,7 +43,7 @@ - */ - mismatchedIndentation() {} - -- inline /* foo*/(/* bar */) /* baz */ {} -+ inline /* foo*/ (/* bar */) /* baz */ {} - - noBody(/* comment */ arg); - } -``` - -# Output - -```js -export class Point { - /** - * Does something. - */ - foo() {} - - /** - * Does something else. - */ - bar() {} - - /** - * Does - * something - * much - * better - * than - * the - * rest. - */ - baz() {} - - /** - * Buzz-Fizz. - * Note: This is indented too far. - */ - fizzBuzz() {} - - /** - * Turns the given string into pig-latin. - */ - pigLatinize(value: string) { - /** - * This is a block comment inside of a method. - */ - } - - /** - * One - * Two - * Three - * Four - */ - mismatchedIndentation() {} - - inline /* foo*/ (/* bar */) /* baz */ {} - - noBody(/* comment */ arg); -} -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/type-parameters.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/type-parameters.ts.snap index b77ce3cf89b..372dde289a9 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/type-parameters.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/type-parameters.ts.snap @@ -1,5 +1,7 @@ --- source: crates/rome_js_formatter/tests/prettier_tests.rs +info: + test_file: typescript/comments/type-parameters.ts --- # Input @@ -42,53 +44,43 @@ type T = < ```diff --- Prettier +++ Rome -@@ -1,18 +1,18 @@ --functionName(); --const a: T = 1; --functionName(); --function foo() {} -+functionName(); -+const a: T< /* comment */ > = 1; -+functionName< /* comment */ >(); -+function foo< /* comment */ >() {} +@@ -3,7 +3,7 @@ + functionName(); + function foo() {} interface Foo { - (arg): any; -+ < /* comment */ >(arg): any; ++ (arg): any; } --type T = (arg) => any; -+type T = < /* comment */ >(arg) => any; + type T = (arg) => any; - functionName(); // comment - const a: T< -- // comment -+// comment - > = 1; - functionName< -- // comment -+// comment - >(); - function foo< +@@ -26,6 +26,4 @@ + } + type T = < // comment +->( +- arg, +-) => any; ++>(arg) => any; ``` # Output ```js -functionName(); -const a: T< /* comment */ > = 1; -functionName< /* comment */ >(); -function foo< /* comment */ >() {} +functionName(); +const a: T = 1; +functionName(); +function foo() {} interface Foo { - < /* comment */ >(arg): any; + (arg): any; } -type T = < /* comment */ >(arg) => any; +type T = (arg) => any; functionName(); // comment const a: T< -// comment + // comment > = 1; functionName< -// comment + // comment >(); function foo< // comment @@ -102,9 +94,7 @@ interface Foo { } type T = < // comment ->( - arg, -) => any; +>(arg) => any; ``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/union.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/union.ts.snap deleted file mode 100644 index 9159b8f00eb..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/comments/union.ts.snap +++ /dev/null @@ -1,85 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -type UploadState - // The upload hasnt begun yet - = {type: "Not_begun"} - // The upload timed out - | {type: "Timed_out"} - // Failed somewhere on the line - | {type: "Failed", error: E, errorMsg: EM} - // Uploading to aws3 and CreatePostMutation succeeded - | {type: "Success", data: D}; - -type UploadState2 - // The upload hasnt begun yet - = A - // The upload timed out - | B - // Failed somewhere on the line - | C - // Uploading to aws3 and CreatePostMutation succeeded - | D; -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,5 +1,6 @@ --type UploadState = -- // The upload hasnt begun yet -+type UploadState -+// The upload hasnt begun yet -+= - | { type: "Not_begun" } - // The upload timed out - | { type: "Timed_out" } -@@ -8,8 +9,9 @@ - // Uploading to aws3 and CreatePostMutation succeeded - | { type: "Success"; data: D }; - --type UploadState2 = -- // The upload hasnt begun yet -+type UploadState2 -+// The upload hasnt begun yet -+= - | A - // The upload timed out - | B -``` - -# Output - -```js -type UploadState -// The upload hasnt begun yet -= - | { type: "Not_begun" } - // The upload timed out - | { type: "Timed_out" } - // Failed somewhere on the line - | { type: "Failed"; error: E; errorMsg: EM } - // Uploading to aws3 and CreatePostMutation succeeded - | { type: "Success"; data: D }; - -type UploadState2 -// The upload hasnt begun yet -= - | A - // The upload timed out - | B - // Failed somewhere on the line - | C - // Uploading to aws3 and CreatePostMutation succeeded - | D; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/conditional-types/comments.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/conditional-types/comments.ts.snap deleted file mode 100644 index 738b3642f4b..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/conditional-types/comments.ts.snap +++ /dev/null @@ -1,218 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -type A = B extends T - ? // comment - foo - : bar; - -type A = B extends test /* comment - comment - comment -*/ - ? foo - : bar; - -type T = test extends B - ? /* comment - comment - comment - comment - */ - foo - : bar; - -type T = test extends B - ? /* comment - comment - comment - comment - */ - foo - : test extends B - ? /* comment - comment - comment */ - foo - : bar; - -type T = test extends B - ? /* comment */ - foo - : bar; - -type T = test extends B - ? foo - : /* comment - comment - comment - comment - */ - bar; - -type T = test extends B - ? foo - : /* comment - comment - comment - comment - */ - test extends B - ? foo - : /* comment - comment - comment - */ - bar; - -type T = test extends B - ? foo - : /* comment */ - bar; - -type T = test extends B ? test extends B /* c -c */? foo : bar : bar; -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,6 +1,5 @@ - type A = B extends T -- ? // comment -- foo -+ ? foo // comment - : bar; - - type A = B extends test /* comment -@@ -15,8 +14,7 @@ - comment - comment - comment -- */ -- foo -+ */ foo - : bar; - - type T = test extends B -@@ -24,13 +22,11 @@ - comment - comment - comment -- */ -- foo -+ */ foo - : test extends B - ? /* comment - comment -- comment */ -- foo -+ comment */ foo - : bar; - - type T = test extends B ? /* comment */ foo : bar; -@@ -41,8 +37,7 @@ - comment - comment - comment -- */ -- bar; -+ */ bar; - - type T = test extends B - ? foo -@@ -50,14 +45,12 @@ - comment - comment - comment -- */ -- test extends B -+ */ test extends B - ? foo - : /* comment - comment - comment -- */ -- bar; -+ */ bar; - - type T = test extends B ? foo : /* comment */ bar; - -``` - -# Output - -```js -type A = B extends T - ? foo // comment - : bar; - -type A = B extends test /* comment - comment - comment -*/ - ? foo - : bar; - -type T = test extends B - ? /* comment - comment - comment - comment - */ foo - : bar; - -type T = test extends B - ? /* comment - comment - comment - comment - */ foo - : test extends B - ? /* comment - comment - comment */ foo - : bar; - -type T = test extends B ? /* comment */ foo : bar; - -type T = test extends B - ? foo - : /* comment - comment - comment - comment - */ bar; - -type T = test extends B - ? foo - : /* comment - comment - comment - comment - */ test extends B - ? foo - : /* comment - comment - comment - */ bar; - -type T = test extends B ? foo : /* comment */ bar; - -type T = test extends B - ? test extends B /* c -c */ - ? foo - : bar - : bar; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/conformance/types/mappedType/mappedType.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/conformance/types/mappedType/mappedType.ts.snap deleted file mode 100644 index 5daf2533ae2..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/conformance/types/mappedType/mappedType.ts.snap +++ /dev/null @@ -1,37 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -type Keys = 'option1' | 'option2'; -type Flags = { [K in Keys]: boolean }; - -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,2 +1,4 @@ - type Keys = "option1" | "option2"; --type Flags = { [K in Keys]: boolean }; -+type Flags = { -+ [K in Keys]: boolean; -+}; -``` - -# Output - -```js -type Keys = "option1" | "option2"; -type Flags = { - [K in Keys]: boolean; -}; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/custom/typeParameters/variables.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/custom/typeParameters/variables.ts.snap index 657861d47b1..57957fc60a4 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/custom/typeParameters/variables.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/custom/typeParameters/variables.ts.snap @@ -34,23 +34,8 @@ const fooooooooooooooo: SomeThing = looooooooooooooooooooooooo ```diff --- Prettier +++ Rome -@@ -1,18 +1,20 @@ - const foo: SomeThing = func(); - const bar: SomeThing = func(); --const fooo: SomeThing<{ [P in "x" | "y"]: number }> = func(); -+const fooo: SomeThing<{ -+ [P in "x" | "y"]: number; -+}> = func(); - const baar: SomeThing = func(); - const fooooooooooooooo: SomeThing = +@@ -10,9 +10,8 @@ looooooooooooooooooooooooooooooongNameFunc(); - const baaaaaaaaaaaaaaaaaaaaar: SomeThing = - looooooooooooooooooooooooooooooongNameFunc(); --const baaaaaaaaaaaaaaar: SomeThing<{ [P in "x" | "y"]: number }> = -- looooooooooooooooooooooooooooooongNameFunc(); -+const baaaaaaaaaaaaaaar: SomeThing<{ -+ [P in "x" | "y"]: number; -+}> = looooooooooooooooooooooooooooooongNameFunc(); const baaaaaaaaaaaaaaaar: SomeThing = looooooooooooooooooooooooooooooongNameFunc(); -const isAnySuccessfulAttempt$: Observable = this._quizService @@ -68,17 +53,14 @@ const fooooooooooooooo: SomeThing = looooooooooooooooooooooooo ```js const foo: SomeThing = func(); const bar: SomeThing = func(); -const fooo: SomeThing<{ - [P in "x" | "y"]: number; -}> = func(); +const fooo: SomeThing<{ [P in "x" | "y"]: number }> = func(); const baar: SomeThing = func(); const fooooooooooooooo: SomeThing = looooooooooooooooooooooooooooooongNameFunc(); const baaaaaaaaaaaaaaaaaaaaar: SomeThing = looooooooooooooooooooooooooooooongNameFunc(); -const baaaaaaaaaaaaaaar: SomeThing<{ - [P in "x" | "y"]: number; -}> = looooooooooooooooooooooooooooooongNameFunc(); +const baaaaaaaaaaaaaaar: SomeThing<{ [P in "x" | "y"]: number }> = + looooooooooooooooooooooooooooooongNameFunc(); const baaaaaaaaaaaaaaaar: SomeThing = looooooooooooooooooooooooooooooongNameFunc(); const isAnySuccessfulAttempt$: Observable = diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/decorators.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/decorators.ts.snap index 54455e67c94..9cf719c4911 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/decorators.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/decorators.ts.snap @@ -1,5 +1,7 @@ --- source: crates/rome_js_formatter/tests/prettier_tests.rs +info: + test_file: typescript/decorators/decorators.ts --- # Input @@ -90,7 +92,15 @@ class Class6 { ```diff --- Prettier +++ Rome -@@ -6,7 +6,7 @@ +@@ -1,12 +1,14 @@ + export class TestTextFileService { +- constructor(@ILifecycleService lifecycleService) {} ++ constructor( ++ @ILifecycleService lifecycleService, ++ ) {} + } + + @commonEditorContribution export class TabCompletionController {} @Component({ @@ -99,26 +109,31 @@ class Class6 { }) class AngularComponent { @Input() myInput: string; -@@ -44,6 +44,7 @@ - class Class4 { - method( - param1, -+ - @Decorator - { prop1, prop2 }: Type, - ) {} -@@ -54,8 +55,14 @@ +@@ -50,12 +52,24 @@ + } + + class Class5 { +- method(@Decorator { prop1 }: Type) {} ++ method( ++ @Decorator { prop1 }: Type, ++ ) {} } class Class6 { - method(@Decorator({}) { prop1 }: Type) {} - method(@Decorator({}) { prop1 }: Type) {} +- method(@Decorator({}) { prop1 }: Type) {} +- method(@Decorator([]) { prop1 }: Type) {} - method(@Decorator([]) { prop1 }: Type) {} + method( ++ @Decorator({}) { prop1 }: Type, ++ ) {} ++ method( + @Decorator( + {}) { prop1 }: Type, + ) {} - method(@Decorator([]) { prop1 }: Type) {} ++ method( ++ @Decorator([]) { prop1 }: Type, ++ ) {} + method( + @Decorator( + []) { prop1 }: Type, @@ -130,7 +145,9 @@ class Class6 { ```js export class TestTextFileService { - constructor(@ILifecycleService lifecycleService) {} + constructor( + @ILifecycleService lifecycleService, + ) {} } @commonEditorContribution @@ -175,23 +192,28 @@ class Class3 { class Class4 { method( param1, - @Decorator { prop1, prop2 }: Type, ) {} } class Class5 { - method(@Decorator { prop1 }: Type) {} + method( + @Decorator { prop1 }: Type, + ) {} } class Class6 { - method(@Decorator({}) { prop1 }: Type) {} + method( + @Decorator({}) { prop1 }: Type, + ) {} method( @Decorator( {}) { prop1 }: Type, ) {} - method(@Decorator([]) { prop1 }: Type) {} + method( + @Decorator([]) { prop1 }: Type, + ) {} method( @Decorator( []) { prop1 }: Type, diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/inline-decorators.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/inline-decorators.ts.snap index d16230ec55f..aec46c2358e 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/inline-decorators.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/inline-decorators.ts.snap @@ -1,5 +1,7 @@ --- source: crates/rome_js_formatter/tests/prettier_tests.rs +info: + test_file: typescript/decorators/inline-decorators.ts --- # Input @@ -75,13 +77,12 @@ class MyContainerComponent { method1() {} @d1 -@@ -30,22 +30,20 @@ +@@ -30,22 +30,19 @@ constructor( @d1 private x: number, @d2(foo) private y: number, - @d3("foo") private z: number, + @d3('foo') private z: number, -+ @d4({ - x: string, - }) @@ -142,7 +143,6 @@ class Class3 { @d1 private x: number, @d2(foo) private y: number, @d3('foo') private z: number, - @d4({ x: string }) private a: string, @@ -163,6 +163,6 @@ class MyContainerComponent { # Lines exceeding max width of 80 characters ``` - 48: @ContentChildren(MyComponent) components: QueryListSomeBigName; + 47: @ContentChildren(MyComponent) components: QueryListSomeBigName; ``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/error-recovery/generic.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/error-recovery/generic.ts.snap new file mode 100644 index 00000000000..ead5c7f144f --- /dev/null +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/error-recovery/generic.ts.snap @@ -0,0 +1,145 @@ +--- +source: crates/rome_js_formatter/tests/prettier_tests.rs +info: + test_file: typescript/error-recovery/generic.ts +--- + +# Input + +```js +f1<>(); + +new f2<>(); + +function f3<>() {} + +class f4 { + constructor<>() {} +} + +const f5 = function<>() {} + +interface f6<> { + test<>(); +} + +class f7<> { + test<>() {} +} +``` + + +# Prettier differences + +```diff +--- Prettier ++++ Rome +@@ -8,12 +8,12 @@ + constructor<>() {} + } + +-const f5 = function <>() {}; ++const f5 = function<>() {} + + interface f6<> { +- test<>(); ++ test<>(); + } + + class f7<> { +- test<>() {} ++ test<>() {} + } +``` + +# Output + +```js +f1<>(); + +new f2<>(); + +function f3<>() {} + +class f4 { + constructor<>() {} +} + +const f5 = function<>() {} + +interface f6<> { + test<>(); +} + +class f7<> { + test<>() {} +} +``` + + +# Errors +``` +error[SyntaxError]: expected a type parameter but instead found '>' + ┌─ generic.ts:1:4 + │ +1 │ f1<>(); + │ ^ Expected a type parameter here + +error[SyntaxError]: expected a type parameter but instead found '>' + ┌─ generic.ts:3:8 + │ +3 │ new f2<>(); + │ ^ Expected a type parameter here + +error[SyntaxError]: expected a type parameter but instead found '>' + ┌─ generic.ts:5:13 + │ +5 │ function f3<>() {} + │ ^ Expected a type parameter here + +error[SyntaxError]: expected a type parameter but instead found '>' + ┌─ generic.ts:8:17 + │ +8 │ constructor<>() {} + │ ^ Expected a type parameter here + +error[SyntaxError]: constructors cannot have type parameters. + ┌─ generic.ts:8:16 + │ +8 │ constructor<>() {} + │ ^^ + +error[SyntaxError]: expected a type parameter but instead found '>' + ┌─ generic.ts:11:21 + │ +11 │ const f5 = function<>() {} + │ ^ Expected a type parameter here + +error[SyntaxError]: expected a type parameter but instead found '>' + ┌─ generic.ts:13:14 + │ +13 │ interface f6<> { + │ ^ Expected a type parameter here + +error[SyntaxError]: expected a type parameter but instead found '>' + ┌─ generic.ts:14:10 + │ +14 │ test<>(); + │ ^ Expected a type parameter here + +error[SyntaxError]: expected a type parameter but instead found '>' + ┌─ generic.ts:17:10 + │ +17 │ class f7<> { + │ ^ Expected a type parameter here + +error[SyntaxError]: expected a type parameter but instead found '>' + ┌─ generic.ts:18:10 + │ +18 │ test<>() {} + │ ^ Expected a type parameter here + + +``` + + diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/export/comment.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/export/comment.ts.snap deleted file mode 100644 index cef2de770b9..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/export/comment.ts.snap +++ /dev/null @@ -1,32 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -export function match(): string /* the matching pattern */ -a -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,2 +1,2 @@ --export function match(): string; /* the matching pattern */ -+export function match(): string /* the matching pattern */; - a; -``` - -# Output - -```js -export function match(): string /* the matching pattern */; -a; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/interface2/break.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/interface2/break.ts.snap index 5104cc03914..bcd990ac239 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/interface2/break.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/interface2/break.ts.snap @@ -104,39 +104,6 @@ export interface ExtendsLongOneWithGenerics extends Bar< SomeLongTypeSomeLongTyp } // Declare Interface Break -@@ -68,14 +71,14 @@ - - interface ExtendsMany - extends ASingleGenericInterface< -- Interface1, -- Interface2, -- Interface3, -- Interface4, -- Interface5, -- Interface6, -- Interface7 -- > { -+ Interface1, -+ Interface2, -+ Interface3, -+ Interface4, -+ Interface5, -+ Interface6, -+ Interface7 -+ > { - x: string; - } - -@@ -97,6 +100,6 @@ - - export interface ExtendsLongOneWithGenerics - extends Bar< -- SomeLongTypeSomeLongTypeSomeLongTypeSomeLongType, -- ToBreakLineToBreakLineToBreakLine -- > {} -+ SomeLongTypeSomeLongTypeSomeLongTypeSomeLongType, -+ ToBreakLineToBreakLineToBreakLine -+ > {} ``` # Output @@ -215,14 +182,14 @@ interface ExtendsLarge interface ExtendsMany extends ASingleGenericInterface< - Interface1, - Interface2, - Interface3, - Interface4, - Interface5, - Interface6, - Interface7 - > { + Interface1, + Interface2, + Interface3, + Interface4, + Interface5, + Interface6, + Interface7 + > { x: string; } @@ -244,9 +211,9 @@ interface ExtendsManyWithGenerics export interface ExtendsLongOneWithGenerics extends Bar< - SomeLongTypeSomeLongTypeSomeLongTypeSomeLongType, - ToBreakLineToBreakLineToBreakLine - > {} + SomeLongTypeSomeLongTypeSomeLongTypeSomeLongType, + ToBreakLineToBreakLineToBreakLine + > {} ``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/interface2/comments.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/interface2/comments.ts.snap deleted file mode 100644 index 4eb6fdefd27..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/interface2/comments.ts.snap +++ /dev/null @@ -1,128 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -interface A1 // comment -{ foo(): bar;} - -interface A2 // comment -extends Base -{ foo(): bar;} - -interface A3 // comment1 -extends Base // comment2 -{ foo(): bar;} - -interface A4 // comment1 -extends Base // comment2 - // comment3 -{ foo(): bar;} - -interface A5 // comment1 -extends Base // comment2 - // comment3 -{ // comment4 -foo(): bar;} - -interface A6 // comment1 -extends Base // comment2 - // comment3 -{ -// comment4 -foo(): bar;} -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -15,24 +15,27 @@ - } - - interface A4 // comment1 -- extends Base { -+ extends Base -+// comment3 -+{ - // comment2 -- // comment3 - foo(): bar; - } - - interface A5 // comment1 -- extends Base { -- // comment2 -- // comment3 -+ extends Base -+// comment3 -+{ - // comment4 -+ // comment2 - foo(): bar; - } - - interface A6 // comment1 -- extends Base { -+ extends Base -+// comment3 -+{ - // comment2 -- // comment3 - // comment4 - foo(): bar; - } -``` - -# Output - -```js -interface A1 { - // comment - foo(): bar; -} - -interface A2 // comment - extends Base { - foo(): bar; -} - -interface A3 // comment1 - extends Base { - // comment2 - foo(): bar; -} - -interface A4 // comment1 - extends Base -// comment3 -{ - // comment2 - foo(): bar; -} - -interface A5 // comment1 - extends Base -// comment3 -{ - // comment4 - // comment2 - foo(): bar; -} - -interface A6 // comment1 - extends Base -// comment3 -{ - // comment2 - // comment4 - foo(): bar; -} -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/keyword-types/conditional-types.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/keyword-types/conditional-types.ts.snap deleted file mode 100644 index e1a8d4a8207..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/keyword-types/conditional-types.ts.snap +++ /dev/null @@ -1,56 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -export type UnwrappedResultRow = { - [P in keyof T]: ( - T[P] extends Req ? ( - a - ) : ( - T[P] extends Opt ? ( - b - ) : ( - // TEST - never - ) - ) - ); -}; -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -3,6 +3,7 @@ - ? a - : T[P] extends Opt - ? b -- : // TEST -+ : -+ // TEST - never; - }; -``` - -# Output - -```js -export type UnwrappedResultRow = { - [P in keyof T]: T[P] extends Req - ? a - : T[P] extends Opt - ? b - : - // TEST - never; -}; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/keyword-types/keyword-types-with-parens-comments.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/keyword-types/keyword-types-with-parens-comments.ts.snap deleted file mode 100644 index d321dd2b756..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/keyword-types/keyword-types-with-parens-comments.ts.snap +++ /dev/null @@ -1,168 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -let foo: ( - // comment - any -); -let foo: ( - // comment - null -); -let foo: ( - // comment - this -); -let foo: ( - // comment - number -); -let foo: ( - // comment - void -); -let foo: ( - // comment - boolean -); -let foo: ( - // comment - bigint -); -let foo: ( - // comment - symbol -); -let foo: ( - // comment - string -); -let foo: ( - // comment - never -); -let foo: ( - // comment - object -); -let foo: ( - // comment - undefined -); -let foo: ( - // comment - unknown -); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,26 +1,39 @@ --let foo: // comment -+let foo: -+// comment - any; --let foo: // comment -+let foo: -+// comment - null; --let foo: // comment -+let foo: -+// comment - this; --let foo: // comment -+let foo: -+// comment - number; --let foo: // comment -+let foo: -+// comment - void; --let foo: // comment -+let foo: -+// comment - boolean; --let foo: // comment -+let foo: -+// comment - bigint; --let foo: // comment -+let foo: -+// comment - symbol; --let foo: // comment -+let foo: -+// comment - string; --let foo: // comment -+let foo: -+// comment - never; --let foo: // comment -+let foo: -+// comment - object; --let foo: // comment -+let foo: -+// comment - undefined; --let foo: // comment -+let foo: -+// comment - unknown; -``` - -# Output - -```js -let foo: -// comment -any; -let foo: -// comment -null; -let foo: -// comment -this; -let foo: -// comment -number; -let foo: -// comment -void; -let foo: -// comment -boolean; -let foo: -// comment -bigint; -let foo: -// comment -symbol; -let foo: -// comment -string; -let foo: -// comment -never; -let foo: -// comment -object; -let foo: -// comment -undefined; -let foo: -// comment -unknown; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/keywords/keywords.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/keywords/keywords.ts.snap index 89e4c57740a..cc98ca3000f 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/keywords/keywords.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/keywords/keywords.ts.snap @@ -1,5 +1,7 @@ --- source: crates/rome_js_formatter/tests/prettier_tests.rs +info: + test_file: typescript/keywords/keywords.ts --- # Input @@ -65,7 +67,7 @@ module YYY4 { // Apparently this parses :P - export private public protected static readonly abstract async enum X {} -+ export ++ export + private + public + protected @@ -144,7 +146,7 @@ module Y3 { } // Apparently this parses :P - export + export private public protected diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/mapped-type/mapped-type.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/mapped-type/mapped-type.ts.snap deleted file mode 100644 index 97451ededd9..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/mapped-type/mapped-type.ts.snap +++ /dev/null @@ -1,44 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs ---- - -# Input - -```js -type Keys = 'option1' | 'option2'; -type A = { [K in Keys] }; -type B = { [K in Keys]+? }; -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,3 +1,7 @@ - type Keys = "option1" | "option2"; --type A = { [K in Keys] }; --type B = { [K in Keys]+? }; -+type A = { -+ [K in Keys]; -+}; -+type B = { -+ [K in Keys]+?; -+}; -``` - -# Output - -```js -type Keys = "option1" | "option2"; -type A = { - [K in Keys]; -}; -type B = { - [K in Keys]+?; -}; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/prettier-ignore/mapped-types.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/prettier-ignore/mapped-types.ts.snap index 6059651875e..f4a23cdfa13 100644 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/prettier-ignore/mapped-types.ts.snap +++ b/crates/rome_js_formatter/tests/specs/prettier/typescript/prettier-ignore/mapped-types.ts.snap @@ -1,5 +1,7 @@ --- source: crates/rome_js_formatter/tests/prettier_tests.rs +info: + test_file: typescript/prettier-ignore/mapped-types.ts --- # Input @@ -81,70 +83,42 @@ type a= { ```diff --- Prettier +++ Rome -@@ -1,55 +1,61 @@ - type a = { -- // prettier-ignore -- [A in B]: C | D -- }; -+ // prettier-ignore -+ [A in B]: C | D; -+}; - - type a = { -- [ -- // prettier-ignore -- A in B -- ]: C | D -- }; -+ [ -+ // prettier-ignore -+ A in B]: C | D; -+}; +@@ -11,11 +11,14 @@ + }; type a = { - [A in B]: C | D; // prettier-ignore + [A in -+ // prettier-ignore -+ B]: C | D; ++ // prettier-ignore ++ B]: C | D; }; type a = { - A in B: C | D; // prettier-ignore -+ [A in B]: -+ // prettier-ignore -+ C | D; ++ [A in B]: // prettier-ignore ++ C | D; }; type a = { -- [ -- /* prettier-ignore */ -- A in B -- ]: C | D -- }; -+ [ -+ /* prettier-ignore */ -+ A in B]: C | D; -+}; +@@ -26,11 +29,14 @@ + }; type a = { - [A /* prettier-ignore */ in B]: C | D; + [A in -+ /* prettier-ignore */ -+ B]: C | D; ++ /* prettier-ignore */ ++ B]: C | D; }; type a = { - A in B /* prettier-ignore */: C | D; -+ [A in B]: -+ /* prettier-ignore */ -+ C | D; ++ [A in B]: /* prettier-ignore */ ++ C | D; }; type a = { -- /* prettier-ignore */ [A in B]: C | D -- }; -+ /* prettier-ignore */ [A in B]: C | D; -+}; +@@ -38,15 +44,15 @@ + }; type a = { - [/* prettier-ignore */ A in B ]: C | D @@ -162,61 +136,55 @@ type a= { }; type a = { -- /* prettier-ignore */ -- [A in B]: C | D -- }; -+ /* prettier-ignore */ -+ [A in B]: C | D; -+}; ``` # Output ```js type a = { - // prettier-ignore - [A in B]: C | D; -}; + // prettier-ignore + [A in B]: C | D + }; type a = { - [ - // prettier-ignore - A in B]: C | D; -}; + [ + // prettier-ignore + A in B + ]: C | D + }; type a = { [A in - // prettier-ignore - B]: C | D; + // prettier-ignore + B]: C | D; }; type a = { - [A in B]: - // prettier-ignore - C | D; + [A in B]: // prettier-ignore + C | D; }; type a = { - [ - /* prettier-ignore */ - A in B]: C | D; -}; + [ + /* prettier-ignore */ + A in B + ]: C | D + }; type a = { [A in - /* prettier-ignore */ - B]: C | D; + /* prettier-ignore */ + B]: C | D; }; type a = { - [A in B]: - /* prettier-ignore */ - C | D; + [A in B]: /* prettier-ignore */ + C | D; }; type a = { - /* prettier-ignore */ [A in B]: C | D; -}; + /* prettier-ignore */ [A in B]: C | D + }; type a = { [/* prettier-ignore */ A in B]: C | D; @@ -231,9 +199,9 @@ type a = { }; type a = { - /* prettier-ignore */ - [A in B]: C | D; -}; + /* prettier-ignore */ + [A in B]: C | D + }; ``` diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/typeof-this/decorators.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/typeof-this/decorators.ts.snap deleted file mode 100644 index e9c459e11a2..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/typeof-this/decorators.ts.snap +++ /dev/null @@ -1,46 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs -info: - test_file: typescript/typeof-this/decorators.ts ---- - -# Input - -```js -// https://github.com/typescript-eslint/typescript-eslint/pull/4382 -function decorator() {} -@decorator -class Foo { - bar(baz: typeof this) {} -} -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,5 +1,6 @@ - // https://github.com/typescript-eslint/typescript-eslint/pull/4382 - function decorator() {} -+ - @decorator - class Foo { - bar(baz: typeof this) {} -``` - -# Output - -```js -// https://github.com/typescript-eslint/typescript-eslint/pull/4382 -function decorator() {} - -@decorator -class Foo { - bar(baz: typeof this) {} -} -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/union/inlining.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/union/inlining.ts.snap deleted file mode 100644 index 5e13f16bc20..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/union/inlining.ts.snap +++ /dev/null @@ -1,134 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs -info: - test_file: typescript/union/inlining.ts ---- - -# Input - -```js -interface RelayProps { - articles: a | null, -} -interface RelayProps { - articles: Array<{ - __id: string, - } | null> | null | void, -} - -type UploadState - // The upload hasnt begun yet - = {type: "Not_begun"} - // The upload timed out - | {type: "Timed_out"} - // Failed somewhere on the line - | {type: "Failed", error: E, errorMsg: EM} - // Uploading to aws3 and CreatePostMutation succeeded - | {type: "Success", data: D}; - -type UploadState2 - // The upload hasnt begun yet - = A - // The upload timed out - | B - // Failed somewhere on the line - | C - // Uploading to aws3 and CreatePostMutation succeeded - | D; - -type window = Window & { - __REDUX_DEVTOOLS_EXTENSION_COMPOSE__: Function; -}; - -type T1 = (number | string)["toString"]; -type T2 = ((number | string))["toString"]; -type T3 = (((number | string)))["toString"]; -type T4 = ((((number | string))))["toString"]; -type T5 = number | ((arg: any) => void); -type T6 = number | (((arg: any) => void)); -type T7 = number | ((((arg: any) => void))); -type T8 = number | (((((arg: any) => void)))); -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -7,8 +7,9 @@ - } | null> | null | void; - } - --type UploadState = -- // The upload hasnt begun yet -+type UploadState -+// The upload hasnt begun yet -+= - | { type: "Not_begun" } - // The upload timed out - | { type: "Timed_out" } -@@ -17,8 +18,9 @@ - // Uploading to aws3 and CreatePostMutation succeeded - | { type: "Success"; data: D }; - --type UploadState2 = -- // The upload hasnt begun yet -+type UploadState2 -+// The upload hasnt begun yet -+= - | A - // The upload timed out - | B -``` - -# Output - -```js -interface RelayProps { - articles: a | null; -} -interface RelayProps { - articles: Array<{ - __id: string; - } | null> | null | void; -} - -type UploadState -// The upload hasnt begun yet -= - | { type: "Not_begun" } - // The upload timed out - | { type: "Timed_out" } - // Failed somewhere on the line - | { type: "Failed"; error: E; errorMsg: EM } - // Uploading to aws3 and CreatePostMutation succeeded - | { type: "Success"; data: D }; - -type UploadState2 -// The upload hasnt begun yet -= - | A - // The upload timed out - | B - // Failed somewhere on the line - | C - // Uploading to aws3 and CreatePostMutation succeeded - | D; - -type window = Window & { - __REDUX_DEVTOOLS_EXTENSION_COMPOSE__: Function; -}; - -type T1 = (number | string)["toString"]; -type T2 = (number | string)["toString"]; -type T3 = (number | string)["toString"]; -type T4 = (number | string)["toString"]; -type T5 = number | ((arg: any) => void); -type T6 = number | ((arg: any) => void); -type T7 = number | ((arg: any) => void); -type T8 = number | ((arg: any) => void); -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/union/prettier-ignore.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/union/prettier-ignore.ts.snap deleted file mode 100644 index 17014fa8b06..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/union/prettier-ignore.ts.snap +++ /dev/null @@ -1,103 +0,0 @@ ---- -source: crates/rome_js_formatter/tests/prettier_tests.rs -info: - test_file: typescript/union/prettier-ignore.ts ---- - -# Input - -```js -export type a = - // foo - | foo1&foo2 - // bar - | bar1&bar2 - // prettier-ignore - | qux1&qux2; - -export type a = - // foo - | foo1&foo2 - // bar - | bar1&bar2 - // prettier-ignore - | qux1&qux2 - // baz - | baz1&baz2; - -export type a = - // prettier-ignore - | foo1&foo2 - // bar - | bar1&bar2 - // qux - | qux1&qux2; -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -4,7 +4,7 @@ - // bar - | (bar1 & bar2) - // prettier-ignore -- | qux1&qux2; -+ | (qux1 & qux2); - - export type a = - // foo -@@ -12,7 +12,7 @@ - // bar - | (bar1 & bar2) - // prettier-ignore -- | qux1&qux2 -+ | (qux1 & qux2) - // baz - | (baz1 & baz2); - -@@ -20,6 +20,6 @@ - // prettier-ignore - | foo1&foo2 - // bar -- | (bar1 & bar2) -+ | bar1&bar2 - // qux -- | (qux1 & qux2); -+ | qux1&qux2; -``` - -# Output - -```js -export type a = - // foo - | (foo1 & foo2) - // bar - | (bar1 & bar2) - // prettier-ignore - | (qux1 & qux2); - -export type a = - // foo - | (foo1 & foo2) - // bar - | (bar1 & bar2) - // prettier-ignore - | (qux1 & qux2) - // baz - | (baz1 & baz2); - -export type a = - // prettier-ignore - | foo1&foo2 - // bar - | bar1&bar2 - // qux - | qux1&qux2; -``` - - - diff --git a/crates/rome_js_formatter/tests/specs/ts/assignment/assignment.ts.snap b/crates/rome_js_formatter/tests/specs/ts/assignment/assignment.ts.snap index ae7bc0f84b4..0ff72b43b8b 100644 --- a/crates/rome_js_formatter/tests/specs/ts/assignment/assignment.ts.snap +++ b/crates/rome_js_formatter/tests/specs/ts/assignment/assignment.ts.snap @@ -28,7 +28,7 @@ loooooooooooooooooooooooooong1 = loooooooooooooooooooooooooong2 = void void "looooooooooooooooooooooooooooooooooooooooooog"!; // rome-ignore format: test - loooooooooooooooooooooooooong6 = +loooooooooooooooooooooooooong6 = void "looooooooooooooooooooooooooooooooooooooooooog"!; loooooooooooooooooooooooooong7 = // rome-ignore format: test diff --git a/crates/rome_js_formatter/tests/specs/ts/declaration/interface.ts.snap b/crates/rome_js_formatter/tests/specs/ts/declaration/interface.ts.snap index e4132e621be..247753e2489 100644 --- a/crates/rome_js_formatter/tests/specs/ts/declaration/interface.ts.snap +++ b/crates/rome_js_formatter/tests/specs/ts/declaration/interface.ts.snap @@ -35,8 +35,7 @@ Quote style: Double Quotes Quote properties: As needed ----- interface A {} -interface B extends A { - /** comment **/ +interface B extends A /** comment **/ { something: string; } diff --git a/crates/rome_js_formatter/tests/specs/ts/decoartors.ts.snap b/crates/rome_js_formatter/tests/specs/ts/decoartors.ts.snap index 49174ff2194..8945f7ee7a8 100644 --- a/crates/rome_js_formatter/tests/specs/ts/decoartors.ts.snap +++ b/crates/rome_js_formatter/tests/specs/ts/decoartors.ts.snap @@ -93,7 +93,23 @@ class Test2 { @test /* trailing multiline comment for decorator */ @anotherDecorator() + // leading comment prop: string; } + +## Unimplemented nodes/tokens + +"@sealed" => 0..7 +"\t@readonl" => 21..30 +"\t\t@par" => 62..68 +"\t\t@readon" => 77..86 +"\t\t@aVeryLongDecoratorNameLetsSeeWhatHappensWith" => 104..151 +"@param" => 175..181 +"@param" => 219..225 +"@sealed" => 239..246 +"@sealed" => 272..279 +"@test" => 338..343 +"\t@test /* trailing multiline comment\n\t for decorator */ @anotherDecorator(" => 449..523 + diff --git a/crates/rome_js_formatter/tests/specs/ts/suppressions.ts.snap b/crates/rome_js_formatter/tests/specs/ts/suppressions.ts.snap index 1e5709bd059..1c6da56df1a 100644 --- a/crates/rome_js_formatter/tests/specs/ts/suppressions.ts.snap +++ b/crates/rome_js_formatter/tests/specs/ts/suppressions.ts.snap @@ -21,7 +21,7 @@ Quote properties: As needed ----- interface Suppressions { // rome-ignore format: test - a: void + a: void b: void; } diff --git a/crates/rome_js_formatter/tests/specs/ts/type/conditional.ts.snap b/crates/rome_js_formatter/tests/specs/ts/type/conditional.ts.snap index 3120a24de3e..8fbd8af7aa6 100644 --- a/crates/rome_js_formatter/tests/specs/ts/type/conditional.ts.snap +++ b/crates/rome_js_formatter/tests/specs/ts/type/conditional.ts.snap @@ -44,21 +44,18 @@ type T2 = test extends string : undefined; type T3 = test extends string - ? - // something + ? // something unknown : test extends number ? undefined - : - // else + : // else undefined; type T4 = test extends string - // something - ? unknown + ? // something + unknown : test extends number ? undefined - : - // else + : // else undefined; diff --git a/crates/rome_js_formatter/tests/specs/ts/type/intersection_type.ts.snap b/crates/rome_js_formatter/tests/specs/ts/type/intersection_type.ts.snap index 59ae21d8a90..23bf68c433f 100644 --- a/crates/rome_js_formatter/tests/specs/ts/type/intersection_type.ts.snap +++ b/crates/rome_js_formatter/tests/specs/ts/type/intersection_type.ts.snap @@ -126,8 +126,8 @@ type State = { // spec cases //retain comment case -type TypeWithComments = /*1*/ - /*2*/ /*3*/ {} /*4*/ & /*5*/ number[] /*6*/ & /*7*/ SomeType /*8*/; +type TypeWithComments = /*1*/ /*2*/ /*3*/ {} /*4*/ & /*5*/ number[] /*6*/ & + /*7*/ SomeType /*8*/; type IndentAfterDifferentType1 = {} & SomeLongType & { somelonglonglongkey: number; diff --git a/crates/rome_js_formatter/tests/specs/ts/type/union_type.ts.snap b/crates/rome_js_formatter/tests/specs/ts/type/union_type.ts.snap index e6c57e353c0..af800684f85 100644 --- a/crates/rome_js_formatter/tests/specs/ts/type/union_type.ts.snap +++ b/crates/rome_js_formatter/tests/specs/ts/type/union_type.ts.snap @@ -290,17 +290,14 @@ type LongUnion = type Comments = // leading separator - | - // leading type - A - | B /* -trailing type */; + | // leading type + A + | B; /* +trailing type */ type A = [ - | - /*leading comment with new line*/ - A - | B, + /*leading comment with new line*/ + A | B, ]; type RemoveLeadingSeparatorIfNotBreak = /*a*/ /*b*/ A | B; @@ -309,7 +306,8 @@ type BreakLongTypeAddedLeadingSeparator = | BBBBBBBBBBBBBBBBBBBBBBBB | CCCCCCCCCCCCCCCCCCCCCCCCCCC | DDDDDDDDDDDDDDDDDDDDDDDDDDDDD; -type BreakLongTypeWithLeadingComment = /*leading comment*/ +type BreakLongTypeWithLeadingComment = + /*leading comment*/ | BBBBBBBBBBBBBBBBBBBBBBBB | CCCCCCCCCCCCCCCCCCCCCCCCCCC | DDDDDDDDDDDDDDDDDDDDDDDDDDDDD; @@ -365,10 +363,10 @@ const fooo: SomeThingWithShortMappedType<{ const fooo: SomeThingWithLongMappedType<{ [P in - | AAAAAAAAAAAAAAAAA - | BBBBBBBBBBBB - | CCCCCCCCCCCCCCCCCCCCC - | DDDDDDDDDDDDDDDDDDDDDDDDDDDDD]: number; + | AAAAAAAAAAAAAAAAA + | BBBBBBBBBBBB + | CCCCCCCCCCCCCCCCCCCCC + | DDDDDDDDDDDDDDDDDDDDDDDDDDDDD]: number; }> = {}; export type A = diff --git a/crates/rome_service/src/workspace_types.rs b/crates/rome_service/src/workspace_types.rs index 3a2674eaff3..ec793f24af3 100644 --- a/crates/rome_service/src/workspace_types.rs +++ b/crates/rome_service/src/workspace_types.rs @@ -65,6 +65,7 @@ fn instance_type<'a>( if let Some(description) = description { let comment = format!("/**\n\t* {} \n\t */", description); let trivia = vec![ + (TriviaPieceKind::Newline, "\n"), (TriviaPieceKind::MultiLineComment, comment.as_str()), (TriviaPieceKind::Newline, "\n"), ]; @@ -337,6 +338,7 @@ pub fn generate_type<'a>( if let Some(description) = description { let comment = format!("/**\n\t* {} \n\t */", description); let trivia = vec![ + (TriviaPieceKind::Newline, "\n"), (TriviaPieceKind::MultiLineComment, comment.as_str()), (TriviaPieceKind::Newline, "\n"), ]; diff --git a/xtask/bench/Cargo.toml b/xtask/bench/Cargo.toml index ebe77d3f59a..6ad24dc2001 100644 --- a/xtask/bench/Cargo.toml +++ b/xtask/bench/Cargo.toml @@ -23,6 +23,8 @@ url = "2.2.2" itertools = "0.10.3" ansi_rgb = "0.2.0" +countme = "3.0.1" + # dhat-on dhat = { version = "0.3.0", optional = true } humansize = {version = "1.1.1", optional = true } @@ -35,3 +37,4 @@ tikv-jemallocator = "0.5.0" [features] dhat-heap = ["dhat", "humansize"] +count = ["countme/print_at_exit"] diff --git a/xtask/codegen/src/formatter.rs b/xtask/codegen/src/formatter.rs index b044d6e71b3..ba707c0c1fd 100644 --- a/xtask/codegen/src/formatter.rs +++ b/xtask/codegen/src/formatter.rs @@ -357,18 +357,13 @@ pub fn generate_formatter() { } NodeKind::Unknown => { quote! { - use crate::prelude::*; - use crate::{FormatNodeFields}; - use rome_rowan::AstNode; + use crate::FormatUnknownNodeRule; use rome_js_syntax::#node_id; #[derive(Debug, Clone, Default)] pub struct #format_id; - impl FormatNodeRule<#node_id> for #format_id { - fn fmt_fields(&self, node: &#node_id, f: &mut JsFormatter) -> FormatResult<()> { - format_unknown_node(node.syntax()).fmt(f) - } + impl FormatUnknownNodeRule<#node_id> for #format_id { } } } @@ -437,15 +432,23 @@ impl BoilerplateImpls { fn push(&mut self, kind: &NodeKind, node_id: &Ident, format_id: &TokenStream) { let format_rule_impl = match kind { NodeKind::List { .. } | NodeKind::Union { .. } => quote!(), - _ => quote! { - impl FormatRule for #format_id { - type Context = JsFormatContext; - #[inline(always)] - fn fmt(&self, node: &rome_js_syntax::#node_id, f: &mut JsFormatter) -> FormatResult<()> { - FormatNodeRule::::fmt(self, node, f) + kind => { + let rule = if matches!(kind, NodeKind::Unknown) { + Ident::new("FormatUnknownNodeRule", Span::call_site()) + } else { + Ident::new("FormatNodeRule", Span::call_site()) + }; + + quote! { + impl FormatRule for #format_id { + type Context = JsFormatContext; + #[inline(always)] + fn fmt(&self, node: &rome_js_syntax::#node_id, f: &mut JsFormatter) -> FormatResult<()> { + #rule::::fmt(self, node, f) + } } } - }, + } }; self.impls.push(quote! { @@ -474,7 +477,7 @@ impl BoilerplateImpls { let tokens = quote! { use rome_formatter::{FormatRefWithRule, FormatOwnedWithRule, FormatRule, FormatResult}; - use crate::{AsFormat, IntoFormat, FormatNodeRule, JsFormatter, JsFormatContext}; + use crate::{AsFormat, IntoFormat, FormatNodeRule, FormatUnknownNodeRule, JsFormatter, JsFormatContext}; #( #impls )* }; diff --git a/xtask/codegen/src/generate_bindings.rs b/xtask/codegen/src/generate_bindings.rs index d3b1417ec69..1c9dcd6790d 100644 --- a/xtask/codegen/src/generate_bindings.rs +++ b/xtask/codegen/src/generate_bindings.rs @@ -194,6 +194,7 @@ pub(crate) fn generate_workspace_bindings(mode: Mode) -> Result<()> { if let Some(description) = description { let comment = format!("/**\n\t* {} \n\t */\n", description); let trivia = vec![ + (TriviaPieceKind::Newline, "\n"), (TriviaPieceKind::MultiLineComment, comment.as_str()), (TriviaPieceKind::Newline, "\n"), ];