From 7ff14a941a40ee32146ce96cc38b3fd920ab0781 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Thu, 15 Sep 2022 11:29:08 +0200 Subject: [PATCH 01/15] Empty File to create placeholder PR --- empty.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 empty.txt diff --git a/empty.txt b/empty.txt new file mode 100644 index 00000000000..e69de29bb2d From 9977d282e7b4a12210febd052869bfa64d6ef6bb Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Thu, 15 Sep 2022 14:26:55 +0200 Subject: [PATCH 02/15] Empty File to create placeholder PR --- empty.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 empty.txt diff --git a/empty.txt b/empty.txt deleted file mode 100644 index e69de29bb2d..00000000000 From 8c0ee68e6a16993a99b528e8490fa0c6bec8e4c9 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Fri, 16 Sep 2022 14:32:47 +0200 Subject: [PATCH 03/15] feat(rome_formatter): Comments multi map (#3230) --- Cargo.lock | 1 + crates/rome_formatter/Cargo.toml | 1 + crates/rome_formatter/src/comments.rs | 2 + crates/rome_formatter/src/comments/map.rs | 820 ++++++++++++++++++++++ 4 files changed, 824 insertions(+) create mode 100644 crates/rome_formatter/src/comments/map.rs diff --git a/Cargo.lock b/Cargo.lock index 33069cdfa8d..646804faacb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1585,6 +1585,7 @@ name = "rome_formatter" version = "0.0.0" dependencies = [ "cfg-if", + "countme", "indexmap", "rome_rowan", "rustc-hash", diff --git a/crates/rome_formatter/Cargo.toml b/crates/rome_formatter/Cargo.toml index c288a1f6035..fde1f730112 100644 --- a/crates/rome_formatter/Cargo.toml +++ b/crates/rome_formatter/Cargo.toml @@ -16,6 +16,7 @@ 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" [features] serde = ["dep:serde", "schemars", "rome_rowan/serde"] diff --git a/crates/rome_formatter/src/comments.rs b/crates/rome_formatter/src/comments.rs index d6c34cad742..4c53a59b443 100644 --- a/crates/rome_formatter/src/comments.rs +++ b/crates/rome_formatter/src/comments.rs @@ -1,3 +1,5 @@ +mod map; + use rome_rowan::{ Direction, Language, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxTriviaPieceComments, WalkEvent, diff --git a/crates/rome_formatter/src/comments/map.rs b/crates/rome_formatter/src/comments/map.rs new file mode 100644 index 00000000000..a60e2d32ad5 --- /dev/null +++ b/crates/rome_formatter/src/comments/map.rs @@ -0,0 +1,820 @@ +use countme::Count; +use rustc_hash::FxHashMap; +use std::fmt::{Debug, Formatter}; +use std::iter::FusedIterator; +use std::num::NonZeroU32; +use std::ops::Range; + +/// An optimized multi-map implementation for storing leading, dangling, and trailing parts for a key. +/// +/// A naive implementation using three multimaps, one to store the leading, dangling, and trailing parts, +/// requires between `keys < allocations < keys * 3` vec allocations. +/// +/// This map implementation optimises for the use case where: +/// * Parts belonging to the same key are inserted together. For example, all parts for the key `a` are inserted +/// before inserting any parts for the key `b`. +/// * The parts per key are inserted in the following order: leading, dangling, and then trailing parts. +/// +/// Parts inserted in the above mentioned order are stored in a `Vec` shared by all keys to reduce the number +/// of allocations and increased cache locality. The implementation falls back to +/// storing the leading, dangling, and trailing parts of a key in dedicated `Vec`s if the parts +/// aren't inserted in the above described order. However, this comes with a slight performance penalty due to: +/// * Requiring up to three [Vec] allocations, one for the leading, dangling, and trailing parts. +/// * Requires copying already inserted parts for that key (by cloning) into the newly allocated [Vec]s. +/// * Resolving the slices for every part requires an extra level of indirection. +/// +/// ## Limitations +/// +/// The map supports storing up to `u32::MAX - 1` parts. Inserting the `u32::MAX`nth part panics. +/// +/// ## Comments +/// +/// Storing the leading, dangling, and trailing comments is an exemplary use case for this map implementation because +/// it is generally desired to keep the comments in the same order as in the source document. This translates to +/// inserting the comments per node and for every node in leading, dangling, trailing order (same order as this map optimises for). +/// +/// Running Rome formatter on real world use cases showed that more than 99.99% of comments get inserted in +/// the described order. +/// +/// The size limitation isn't a concern for comments because Rome supports source documents with a size up to 4GB (`u32::MAX`) +/// and every comment has at least a size of 2 bytes: +/// * 1 byte for the start sequence, e.g. `#` +/// * 1 byte for the end sequence, e.g. `\n` +/// +/// Meaning, the upper bound for comments parts in a document are `u32::MAX / 2`. +pub(super) struct CommentsMap { + /// Lookup table to retrieve the entry for a key. + index: FxHashMap, + + /// Flat array storing all the parts that have been inserted in order. + parts: Vec, + + /// Vector containing the leading, dangling, and trailing vectors for out of order entries. + /// + /// The length of `out_of_order` is a multiple of 3 where: + /// * `index % 3 == 0`: Leading parts + /// * `index % 3 == 1`: Dangling parts + /// * `index % 3 == 2`: Trailing parts + out_of_order: Vec>, +} + +impl CommentsMap { + pub fn new() -> Self { + Self { + index: FxHashMap::default(), + parts: Vec::new(), + out_of_order: Vec::new(), + } + } + + /// Pushes a leading part for `key`. + pub fn push_leading(&mut self, key: K, part: V) + where + V: Clone, + { + match self.index.get_mut(&key) { + None => { + let start = self.parts.len(); + self.parts.push(part); + + self.index.insert( + key, + Entry::InOrder(InOrderEntry::leading(start..self.parts.len())), + ); + } + + // Has only leading comments and no elements have been pushed since + Some(Entry::InOrder(entry)) + if entry.trailing_start.is_none() && self.parts.len() == entry.range().end => + { + self.parts.push(part); + entry.increment_leading_range(); + } + + Some(Entry::OutOfOrder(entry)) => { + let leading = &mut self.out_of_order[entry.leading_index()]; + leading.push(part); + } + + Some(entry) => { + let out_of_order = + Self::entry_to_out_of_order(entry, &self.parts, &mut self.out_of_order); + self.out_of_order[out_of_order.leading_index()].push(part); + } + } + } + + /// Pushes a dangling part for `key` + pub fn push_dangling(&mut self, key: K, part: V) + where + V: Clone, + { + match self.index.get_mut(&key) { + None => { + let start = self.parts.len(); + self.parts.push(part); + + self.index.insert( + key, + Entry::InOrder(InOrderEntry::dangling(start..self.parts.len())), + ); + } + + // Has leading and dangling comments and its comments are at the end of parts + Some(Entry::InOrder(entry)) + if entry.trailing_end.is_none() && self.parts.len() == entry.range().end => + { + self.parts.push(part); + entry.increment_dangling_range(); + } + + Some(Entry::OutOfOrder(entry)) => { + let dangling = &mut self.out_of_order[entry.dangling_index()]; + dangling.push(part); + } + + Some(entry) => { + let out_of_order = + Self::entry_to_out_of_order(entry, &self.parts, &mut self.out_of_order); + self.out_of_order[out_of_order.dangling_index()].push(part); + } + } + } + + /// Pushes a trailing part for `key`. + pub fn push_trailing(&mut self, key: K, part: V) + where + V: Clone, + { + match self.index.get_mut(&key) { + None => { + let start = self.parts.len(); + self.parts.push(part); + + self.index.insert( + key, + Entry::InOrder(InOrderEntry::trailing(start..self.parts.len())), + ); + } + + // Its comments are at the end + Some(Entry::InOrder(entry)) if entry.range().end == self.parts.len() => { + self.parts.push(part); + entry.increment_trailing_range(); + } + + Some(Entry::OutOfOrder(entry)) => { + let trailing = &mut self.out_of_order[entry.trailing_index()]; + trailing.push(part); + } + + Some(entry) => { + let out_of_order = + Self::entry_to_out_of_order(entry, &self.parts, &mut self.out_of_order); + self.out_of_order[out_of_order.trailing_index()].push(part); + } + } + } + + #[cold] + fn entry_to_out_of_order<'a>( + entry: &'a mut Entry, + parts: &[V], + out_of_order: &mut Vec>, + ) -> &'a mut OutOfOrderEntry + where + V: Clone, + { + match entry { + Entry::InOrder(in_order) => { + let index = out_of_order.len(); + + out_of_order.push(parts[in_order.leading_range()].to_vec()); + out_of_order.push(parts[in_order.dangling_range()].to_vec()); + out_of_order.push(parts[in_order.trailing_range()].to_vec()); + + *entry = Entry::OutOfOrder(OutOfOrderEntry { + leading_index: index, + _count: Count::new(), + }); + + match entry { + Entry::InOrder(_) => unreachable!(), + Entry::OutOfOrder(out_of_order) => out_of_order, + } + } + Entry::OutOfOrder(entry) => entry, + } + } + + /// Retrieves all leading parts of `key` + pub fn leading(&self, key: &K) -> &[V] { + match self.index.get(key) { + None => &[], + Some(Entry::InOrder(in_order)) => &self.parts[in_order.leading_range()], + Some(Entry::OutOfOrder(entry)) => &self.out_of_order[entry.leading_index()], + } + } + + /// Retrieves all dangling parts of `key`. + pub fn dangling(&self, key: &K) -> &[V] { + match self.index.get(key) { + None => &[], + Some(Entry::InOrder(in_order)) => &self.parts[in_order.dangling_range()], + Some(Entry::OutOfOrder(entry)) => &self.out_of_order[entry.dangling_index()], + } + } + + /// Retrieves all trailing parts of `key`. + pub fn trailing(&self, key: &K) -> &[V] { + match self.index.get(key) { + None => &[], + Some(Entry::InOrder(in_order)) => &self.parts[in_order.trailing_range()], + Some(Entry::OutOfOrder(entry)) => &self.out_of_order[entry.trailing_index()], + } + } + + /// Returns `true` if `key` has any leading, dangling, or trailing part. + pub fn has(&self, key: &K) -> bool { + self.index.get(key).is_some() + } + + /// Returns an iterator over all leading, dangling, and trailing parts of `key`. + pub fn parts(&self, key: &K) -> PartsIterator { + match self.index.get(key) { + None => PartsIterator::Slice([].iter()), + Some(Entry::OutOfOrder(entry)) => PartsIterator::Leading { + leading: self.out_of_order[entry.leading_index()].iter(), + dangling: &self.out_of_order[entry.dangling_index()], + trailing: &self.out_of_order[entry.trailing_index()], + }, + Some(Entry::InOrder(entry)) => PartsIterator::Slice(self.parts[entry.range()].iter()), + } + } +} + +impl Default for CommentsMap { + fn default() -> Self { + Self::new() + } +} + +impl std::fmt::Debug for CommentsMap +where + K: std::fmt::Debug, + V: std::fmt::Debug, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut builder = f.debug_map(); + + for (key, entry) in &self.index { + builder.entry(&key, &DebugEntry { entry, map: self }); + } + + builder.finish() + } +} + +/// Iterator to iterate over all leading, dangling, and trailing parts of a key. +pub(super) enum PartsIterator<'a, V> { + /// The slice into the [CommentsMap::parts] [Vec] if this is an in-order entry or the trailing parts + /// of an out-of-order entry. + Slice(std::slice::Iter<'a, V>), + + /// Iterator over the leading parts of an out-of-order entry. Returns the dangling parts, and then the + /// trailing parts once the leading iterator is fully consumed. + Leading { + leading: std::slice::Iter<'a, V>, + dangling: &'a [V], + trailing: &'a [V], + }, + + /// Iterator over the dangling parts of an out-of-order entry. Returns the trailing parts + /// once the leading iterator is fully consumed. + Dangling { + dangling: std::slice::Iter<'a, V>, + trailing: &'a [V], + }, +} + +impl<'a, V> Iterator for PartsIterator<'a, V> { + type Item = &'a V; + + fn next(&mut self) -> Option { + match self { + PartsIterator::Slice(inner) => inner.next(), + + PartsIterator::Leading { + leading, + dangling, + trailing, + } => match leading.next() { + Some(next) => Some(next), + None if !dangling.is_empty() => { + let mut dangling_iterator = dangling.iter(); + let next = dangling_iterator.next().unwrap(); + *self = PartsIterator::Dangling { + dangling: dangling_iterator, + trailing, + }; + Some(next) + } + None => { + let mut trailing_iterator = trailing.iter(); + let next = trailing_iterator.next(); + *self = PartsIterator::Slice(trailing_iterator); + next + } + }, + + PartsIterator::Dangling { dangling, trailing } => match dangling.next() { + Some(next) => Some(next), + None => { + let mut trailing_iterator = trailing.iter(); + let next = trailing_iterator.next(); + *self = PartsIterator::Slice(trailing_iterator); + next + } + }, + } + } + + fn size_hint(&self) -> (usize, Option) { + match self { + PartsIterator::Slice(slice) => slice.size_hint(), + PartsIterator::Leading { + leading, + dangling, + trailing, + } => { + let len = leading.len() + dangling.len() + trailing.len(); + + (len, Some(len)) + } + PartsIterator::Dangling { dangling, trailing } => { + let len = dangling.len() + trailing.len(); + (len, Some(len)) + } + } + } + + fn last(self) -> Option + where + Self: Sized, + { + match self { + PartsIterator::Slice(slice) => slice.last(), + PartsIterator::Leading { + leading, + dangling, + trailing, + } => trailing + .last() + .or_else(|| dangling.last()) + .or_else(|| leading.last()), + PartsIterator::Dangling { dangling, trailing } => { + trailing.last().or_else(|| dangling.last()) + } + } + } +} + +impl ExactSizeIterator for PartsIterator<'_, V> {} + +impl FusedIterator for PartsIterator<'_, V> {} + +#[derive(Debug)] +enum Entry { + InOrder(InOrderEntry), + OutOfOrder(OutOfOrderEntry), +} + +struct DebugEntry<'a, K, V> { + entry: &'a Entry, + map: &'a CommentsMap, +} + +impl Debug for DebugEntry<'_, K, V> +where + K: Debug, + V: Debug, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let leading = match self.entry { + Entry::OutOfOrder(entry) => self.map.out_of_order[entry.leading_index()].as_slice(), + Entry::InOrder(entry) => &self.map.parts[entry.leading_range()], + }; + + let dangling = match self.entry { + Entry::OutOfOrder(entry) => self.map.out_of_order[entry.dangling_index()].as_slice(), + Entry::InOrder(entry) => &self.map.parts[entry.dangling_range()], + }; + + let trailing = match self.entry { + Entry::OutOfOrder(entry) => self.map.out_of_order[entry.trailing_index()].as_slice(), + Entry::InOrder(entry) => &self.map.parts[entry.trailing_range()], + }; + + let mut list = f.debug_list(); + + list.entries(leading.iter().map(DebugValue::Leading)); + list.entries(dangling.iter().map(DebugValue::Dangling)); + list.entries(trailing.iter().map(DebugValue::Trailing)); + + list.finish() + } +} + +enum DebugValue<'a, V> { + Leading(&'a V), + Dangling(&'a V), + Trailing(&'a V), +} + +impl Debug for DebugValue<'_, V> +where + V: Debug, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + DebugValue::Leading(leading) => f.debug_tuple("Leading").field(leading).finish(), + DebugValue::Dangling(dangling) => f.debug_tuple("Dangling").field(dangling).finish(), + DebugValue::Trailing(trailing) => f.debug_tuple("Trailing").field(trailing).finish(), + } + } +} + +#[derive(Debug)] +struct InOrderEntry { + /// Index into the [CommentsMap::parts] vector where the leading parts of this entry start + leading_start: PartIndex, + + /// Index into the [CommentsMap::parts] vector where the dangling parts (and, thus, the leading parts end) start. + dangling_start: PartIndex, + + /// Index into the [CommentsMap::parts] vector where the trailing parts (and, thus, the dangling parts end) of this entry start + trailing_start: Option, + + /// Index into the [CommentsMap::parts] vector where the trailing parts of this entry end + trailing_end: Option, + + _count: Count, +} + +impl InOrderEntry { + fn leading(range: Range) -> Self { + InOrderEntry { + leading_start: PartIndex::from_len(range.start), + dangling_start: PartIndex::from_len(range.end), + trailing_start: None, + trailing_end: None, + _count: Count::new(), + } + } + + fn dangling(range: Range) -> Self { + let start = PartIndex::from_len(range.start); + InOrderEntry { + leading_start: start, + dangling_start: start, + trailing_start: Some(PartIndex::from_len(range.end)), + trailing_end: None, + _count: Count::new(), + } + } + + fn trailing(range: Range) -> Self { + let start = PartIndex::from_len(range.start); + InOrderEntry { + leading_start: start, + dangling_start: start, + trailing_start: Some(start), + trailing_end: Some(PartIndex::from_len(range.end)), + _count: Count::new(), + } + } + + fn increment_leading_range(&mut self) { + assert!( + self.trailing_start.is_none(), + "Can't extend the leading range for an in order entry with dangling comments." + ); + + self.dangling_start.increment(); + } + + fn increment_dangling_range(&mut self) { + assert!( + self.trailing_end.is_none(), + "Can't extend the dangling range for an in order entry with trailing comments." + ); + + match &mut self.trailing_start { + Some(start) => start.increment(), + None => self.trailing_start = Some(self.dangling_start.incremented()), + } + } + + fn increment_trailing_range(&mut self) { + match (self.trailing_start, &mut self.trailing_end) { + // Already has some trailing comments + (Some(_), Some(end)) => end.increment(), + // Has dangling comments only + (Some(start), None) => self.trailing_end = Some(start.incremented()), + // Has leading comments only + (None, None) => { + self.trailing_start = Some(self.dangling_start); + self.trailing_end = Some(self.dangling_start.incremented()) + } + (None, Some(_)) => { + unreachable!() + } + } + } + + fn leading_range(&self) -> Range { + self.leading_start.value()..self.dangling_start.value() + } + + fn dangling_range(&self) -> Range { + match self.trailing_start { + None => self.dangling_start.value()..self.dangling_start.value(), + Some(trailing_start) => self.dangling_start.value()..trailing_start.value(), + } + } + + fn trailing_range(&self) -> Range { + match (self.trailing_start, self.trailing_end) { + (Some(trailing_start), Some(trailing_end)) => { + trailing_start.value()..trailing_end.value() + } + // Only dangling comments + (Some(trailing_start), None) => trailing_start.value()..trailing_start.value(), + (None, Some(_)) => { + panic!("Trailing end shouldn't be set if trailing start is none"); + } + (None, None) => self.dangling_start.value()..self.dangling_start.value(), + } + } + + fn range(&self) -> Range { + self.leading_start.value() + ..self + .trailing_end + .or(self.trailing_start) + .unwrap_or(self.dangling_start) + .value() + } +} + +#[derive(Debug)] +struct OutOfOrderEntry { + /// Index into the [CommentsMap::out_of_order] vector at which offset the leaading vec is stored. + leading_index: usize, + _count: Count, +} + +impl OutOfOrderEntry { + const fn leading_index(&self) -> usize { + self.leading_index + } + + const fn dangling_index(&self) -> usize { + self.leading_index + 1 + } + + const fn trailing_index(&self) -> usize { + self.leading_index + 2 + } +} + +/// Index into the [CommentsMap::parts] vector. +/// +/// Stores the index as a [NonZeroU32], starting at 1 instead of 0 so that +/// `size_of::() == size_of::>()`. +/// +/// This means, that only `u32 - 1` parts can be stored. This should be sufficient for storing comments +/// because: Comments have length of two or more bytes because they consist of a start and end character sequence (`#` + new line, `/*` and `*/`). +/// Thus, a document with length `u32` can have at most `u32::MAX / 2` comment-parts. +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +struct PartIndex(NonZeroU32); + +impl PartIndex { + fn from_len(value: usize) -> Self { + Self(NonZeroU32::try_from(value as u32 + 1).unwrap()) + } + + fn value(&self) -> usize { + (u32::from(self.0) - 1) as usize + } + + fn increment(&mut self) { + *self = self.incremented(); + } + + fn incremented(&self) -> PartIndex { + PartIndex(NonZeroU32::new(self.0.get() + 1).unwrap()) + } +} + +#[cfg(test)] +mod tests { + use crate::comments::map::CommentsMap; + + static EMPTY: [i32; 0] = []; + + #[test] + fn leading_dangling_trailing() { + let mut map = CommentsMap::new(); + + map.push_leading("a", 1); + map.push_dangling("a", 2); + map.push_dangling("a", 3); + map.push_trailing("a", 4); + + assert_eq!(map.parts, vec![1, 2, 3, 4]); + + assert_eq!(map.leading(&"a"), &[1]); + assert_eq!(map.dangling(&"a"), &[2, 3]); + assert_eq!(map.trailing(&"a"), &[4]); + + assert!(map.has(&"a")); + + assert_eq!( + map.parts(&"a").copied().collect::>(), + vec![1, 2, 3, 4] + ); + } + + #[test] + fn dangling_trailing() { + let mut map = CommentsMap::new(); + + map.push_dangling("a", 1); + map.push_dangling("a", 2); + map.push_trailing("a", 3); + + assert_eq!(map.parts, vec![1, 2, 3]); + + assert_eq!(map.leading(&"a"), &EMPTY); + assert_eq!(map.dangling(&"a"), &[1, 2]); + assert_eq!(map.trailing(&"a"), &[3]); + + assert!(map.has(&"a")); + + assert_eq!(map.parts(&"a").copied().collect::>(), vec![1, 2, 3]); + } + + #[test] + fn trailing() { + let mut map = CommentsMap::new(); + + map.push_trailing("a", 1); + map.push_trailing("a", 2); + + assert_eq!(map.parts, vec![1, 2]); + + assert_eq!(map.leading(&"a"), &EMPTY); + assert_eq!(map.dangling(&"a"), &EMPTY); + assert_eq!(map.trailing(&"a"), &[1, 2]); + + assert!(map.has(&"a")); + + assert_eq!(map.parts(&"a").copied().collect::>(), vec![1, 2]); + } + + #[test] + fn empty() { + let map = CommentsMap::<&str, i32>::default(); + + assert_eq!(map.parts, Vec::::new()); + + assert_eq!(map.leading(&"a"), &EMPTY); + assert_eq!(map.dangling(&"a"), &EMPTY); + assert_eq!(map.trailing(&"a"), &EMPTY); + + assert!(!map.has(&"a")); + + assert_eq!( + map.parts(&"a").copied().collect::>(), + Vec::::new() + ); + } + + #[test] + fn multiple_keys() { + let mut map = CommentsMap::new(); + + map.push_leading("a", 1); + map.push_dangling("b", 2); + map.push_trailing("c", 3); + map.push_leading("d", 4); + map.push_dangling("d", 5); + map.push_trailing("d", 6); + + assert_eq!(map.parts, &[1, 2, 3, 4, 5, 6]); + + assert_eq!(map.leading(&"a"), &[1]); + assert_eq!(map.dangling(&"a"), &EMPTY); + assert_eq!(map.trailing(&"a"), &EMPTY); + assert_eq!(map.parts(&"a").copied().collect::>(), vec![1]); + + assert_eq!(map.leading(&"b"), &EMPTY); + assert_eq!(map.dangling(&"b"), &[2]); + assert_eq!(map.trailing(&"b"), &EMPTY); + assert_eq!(map.parts(&"b").copied().collect::>(), vec![2]); + + assert_eq!(map.leading(&"c"), &EMPTY); + assert_eq!(map.dangling(&"c"), &EMPTY); + assert_eq!(map.trailing(&"c"), &[3]); + assert_eq!(map.parts(&"c").copied().collect::>(), vec![3]); + + assert_eq!(map.leading(&"d"), &[4]); + assert_eq!(map.dangling(&"d"), &[5]); + assert_eq!(map.trailing(&"d"), &[6]); + assert_eq!(map.parts(&"d").copied().collect::>(), vec![4, 5, 6]); + } + + #[test] + fn dangling_leading() { + let mut map = CommentsMap::new(); + + map.push_dangling("a", 1); + map.push_leading("a", 2); + map.push_dangling("a", 3); + map.push_trailing("a", 4); + + assert_eq!(map.leading(&"a"), [2]); + assert_eq!(map.dangling(&"a"), [1, 3]); + assert_eq!(map.trailing(&"a"), [4]); + + assert_eq!( + map.parts(&"a").copied().collect::>(), + vec![2, 1, 3, 4] + ); + + assert!(map.has(&"a")); + } + + #[test] + fn trailing_leading() { + let mut map = CommentsMap::new(); + + map.push_trailing("a", 1); + map.push_leading("a", 2); + map.push_dangling("a", 3); + map.push_trailing("a", 4); + + assert_eq!(map.leading(&"a"), [2]); + assert_eq!(map.dangling(&"a"), [3]); + assert_eq!(map.trailing(&"a"), [1, 4]); + + assert_eq!( + map.parts(&"a").copied().collect::>(), + vec![2, 3, 1, 4] + ); + + assert!(map.has(&"a")); + } + + #[test] + fn trailing_dangling() { + let mut map = CommentsMap::new(); + + map.push_trailing("a", 1); + map.push_dangling("a", 2); + map.push_trailing("a", 3); + + assert_eq!(map.leading(&"a"), &EMPTY); + assert_eq!(map.dangling(&"a"), &[2]); + assert_eq!(map.trailing(&"a"), &[1, 3]); + + assert_eq!(map.parts(&"a").copied().collect::>(), vec![2, 1, 3]); + + assert!(map.has(&"a")); + } + + #[test] + fn keys_out_of_order() { + let mut map = CommentsMap::new(); + + map.push_leading("a", 1); + map.push_dangling("b", 2); + map.push_leading("a", 3); + + map.push_trailing("c", 4); + map.push_dangling("b", 5); + + map.push_leading("d", 6); + map.push_trailing("c", 7); + + assert_eq!(map.leading(&"a"), &[1, 3]); + assert_eq!(map.dangling(&"b"), &[2, 5]); + assert_eq!(map.trailing(&"c"), &[4, 7]); + + assert!(map.has(&"a")); + assert!(map.has(&"b")); + assert!(map.has(&"c")); + } +} From f9a0398df3cf7cccc612acfd1546fdfc618dba31 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Thu, 15 Sep 2022 14:01:28 +0200 Subject: [PATCH 04/15] Comments infrastructure --- Cargo.lock | 2 + crates/rome_formatter/Cargo.toml | 4 + crates/rome_formatter/src/comments.rs | 555 ++++++++-- crates/rome_formatter/src/comments/builder.rs | 999 ++++++++++++++++++ crates/rome_formatter/src/lib.rs | 22 +- 5 files changed, 1458 insertions(+), 124 deletions(-) create mode 100644 crates/rome_formatter/src/comments/builder.rs diff --git a/Cargo.lock b/Cargo.lock index 646804faacb..4ad4eab2e64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1587,6 +1587,8 @@ dependencies = [ "cfg-if", "countme", "indexmap", + "rome_js_parser", + "rome_js_syntax", "rome_rowan", "rustc-hash", "schemars", diff --git a/crates/rome_formatter/Cargo.toml b/crates/rome_formatter/Cargo.toml index fde1f730112..5c63d0c7b5b 100644 --- a/crates/rome_formatter/Cargo.toml +++ b/crates/rome_formatter/Cargo.toml @@ -18,5 +18,9 @@ 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" } + [features] serde = ["dep:serde", "schemars", "rome_rowan/serde"] diff --git a/crates/rome_formatter/src/comments.rs b/crates/rome_formatter/src/comments.rs index 4c53a59b443..f022ae8bbee 100644 --- a/crates/rome_formatter/src/comments.rs +++ b/crates/rome_formatter/src/comments.rs @@ -1,12 +1,13 @@ +mod builder; mod map; -use rome_rowan::{ - Direction, Language, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxTriviaPieceComments, - WalkEvent, -}; +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)] @@ -47,43 +48,6 @@ pub enum CommentKind { Line, } -#[derive(Debug, Clone)] -pub struct SourceComment { - /// The number of lines appearing before this comment - lines_before: u32, - - /// The comment piece - piece: SyntaxTriviaPieceComments, -} - -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, - } - } - - /// Creates a leading comment with the specified lines before - pub fn leading(piece: SyntaxTriviaPieceComments, lines_before: u32) -> Self { - Self { - lines_before, - piece, - } - } - - /// Returns the underlining comment trivia piece - pub fn piece(&self) -> &SyntaxTriviaPieceComments { - &self.piece - } - - /// Returns the number of lines before directly before this comment - pub fn lines_before(&self) -> u32 { - self.lines_before - } -} - impl CommentKind { pub const fn is_line(&self) -> bool { matches!(self, CommentKind::Line) @@ -116,24 +80,236 @@ impl CommentKind { } } +#[derive(Debug, Clone)] +pub struct SourceComment { + /// The number of lines appearing before this comment + pub(crate) lines_before: u32, + + pub(crate) lines_after: u32, + + /// The comment piece + pub(crate) piece: SyntaxTriviaPieceComments, + + pub(crate) kind: CommentKind, +} + +impl SourceComment { + /// Returns the underlining comment trivia piece + pub fn piece(&self) -> &SyntaxTriviaPieceComments { + &self.piece + } + + /// Returns the number of lines before directly before this comment + pub fn lines_before(&self) -> u32 { + self.lines_before + } + + pub fn lines_after(&self) -> u32 { + self.lines_after + } + + /// The kind of the comment + pub fn kind(&self) -> CommentKind { + self.kind + } +} + +#[derive(Debug, Clone)] +pub struct DecoratedComment { + enclosing: SyntaxNode, + preceding: Option>, + following: Option>, + following_token: SyntaxToken, + position: CommentTextPosition, + lines_before: u32, + lines_after: u32, + comment: SyntaxTriviaPieceComments, + kind: CommentKind, +} + +impl DecoratedComment { + /// The node that fully encloses the comment (the comment's start and end position are fully in the + /// node's bounds). + pub fn enclosing_node(&self) -> &SyntaxNode { + &self.enclosing + } + + pub fn piece(&self) -> &SyntaxTriviaPieceComments { + &self.comment + } + + /// The node directly preceding the comment or [None] if the comment is preceded by a token or is the first + /// token in the program. + pub fn preceding_node(&self) -> Option<&SyntaxNode> { + self.preceding.as_ref() + } + + fn take_preceding_node(&mut self) -> Option> { + self.preceding.take() + } + + /// The node directly following the comment or [None] if the comment is followed by a token or is the last token in the program. + pub fn following_node(&self) -> Option<&SyntaxNode> { + self.following.as_ref() + } + + fn take_following_node(&mut self) -> Option> { + self.following.take() + } + + /// The number of lines between this comment and the **previous** token, comment or skipped trivia. + pub fn lines_before(&self) -> u32 { + self.lines_before + } + + pub fn lines_after(&self) -> u32 { + self.lines_after + } + + /// Returns the [kind](CommentKind) of the comment. + pub fn kind(&self) -> CommentKind { + self.kind + } + + pub fn position(&self) -> CommentTextPosition { + self.position + } + + pub fn following_token(&self) -> &SyntaxToken { + &self.following_token + } +} + +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, + } + } +} + +/// The position of a comment in the source document. +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum CommentTextPosition { + /// A comment that is separated by at least one line break from the following token + /// + /// ```javascript + /// a; /* this */ // or this + /// b; + EndOfLine, + + /// A Comment that is separated by at least one line break from the preceding token + /// + /// ```javascript + /// a; + /// /* comment */ /* or this */ + /// b; + /// ``` + OwnLine, + + /// A comment that is placed on the same line as the preceding and following token. + /// + /// ```javascript + /// a /* comment */ + b + /// ``` + SameLine, +} + +impl CommentTextPosition { + pub const fn is_same_line(&self) -> bool { + matches!(self, CommentTextPosition::SameLine) + } + + pub const fn is_own_line(&self) -> bool { + matches!(self, CommentTextPosition::OwnLine) + } + + pub const fn is_end_of_line(&self) -> bool { + matches!(self, CommentTextPosition::EndOfLine) + } +} + +#[derive(Debug)] +pub enum CommentPlacement { + /// Overrides the positioning of the comment to be a leading node comment. + Leading { + node: SyntaxNode, + comment: SourceComment, + }, + /// Overrides the positioning of the comment to be a trailing node comment. + Trailing { + node: SyntaxNode, + comment: SourceComment, + }, + + /// Makes this comment a dangling comment of `node` + Dangling { + node: SyntaxNode, + comment: SourceComment, + }, + + /// Uses the default positioning rules for the comment. + /// TODO document rules + Default(DecoratedComment), +} + +impl CommentPlacement { + #[inline] + pub fn leading(node: SyntaxNode, comment: impl Into>) -> Self { + Self::Leading { + node, + comment: comment.into(), + } + } + + pub fn dangling(node: SyntaxNode, comment: impl Into>) -> Self { + Self::Dangling { + node, + comment: comment.into(), + } + } + + #[inline] + pub fn trailing(node: SyntaxNode, comment: impl Into>) -> Self { + Self::Trailing { + node, + comment: comment.into(), + } + } + + #[inline] + pub fn or_else(self, or_else: F) -> Self + where + F: FnOnce(DecoratedComment) -> CommentPlacement, + { + match self { + CommentPlacement::Default(comment) => or_else(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; + + fn place_comment( + &self, + comment: DecoratedComment, + ) -> CommentPlacement { + CommentPlacement::Default(comment) + } } /// Type that stores the comments of a tree and gives access to: @@ -143,7 +319,7 @@ pub trait CommentStyle { /// * the dangling comments of a token /// /// 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] @@ -165,65 +341,117 @@ pub struct Comments { impl Comments { /// Extracts all the suppressions from `root` and its child nodes. - pub fn from_node(root: &SyntaxNode, language: &FormatLanguage) -> Self + 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 = From 6a430dc9b0dd4212356c28e5fd039946fd636c00 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Thu, 22 Sep 2022 08:16:42 +0200 Subject: [PATCH 15/15] chore(xtask): Part 8: Add line breaks before doc comments (#3246) --- Cargo.lock | 1 + crates/rome_service/src/workspace_types.rs | 2 ++ xtask/bench/Cargo.toml | 3 ++ xtask/codegen/src/formatter.rs | 33 ++++++++++++---------- xtask/codegen/src/generate_bindings.rs | 1 + 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 54127814bd9..4d2bbe49ee5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2840,6 +2840,7 @@ name = "xtask_bench" version = "0.0.0" dependencies = [ "ansi_rgb", + "countme", "criterion", "dhat", "humansize", 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"), ];