diff --git a/crates/rome_cli/tests/snapshots/main_commands_format/does_not_format_ignored_directories.snap b/crates/rome_cli/tests/snapshots/main_commands_format/does_not_format_ignored_directories.snap index a5d15daf7b0..eea2c5ce31d 100644 --- a/crates/rome_cli/tests/snapshots/main_commands_format/does_not_format_ignored_directories.snap +++ b/crates/rome_cli/tests/snapshots/main_commands_format/does_not_format_ignored_directories.snap @@ -6,8 +6,8 @@ expression: content ```json { - "formatter": { - "ignore": [ + "formatter": { + "ignore": [ "test1.js", "./test2.js", "./test3/**/*", @@ -16,7 +16,7 @@ expression: content "**/test6/*.js", "*.test7.js" ] - } + } } ``` diff --git a/crates/rome_js_formatter/src/js/module/export_named_from_clause.rs b/crates/rome_js_formatter/src/js/module/export_named_from_clause.rs index 83970625895..13f1172afed 100644 --- a/crates/rome_js_formatter/src/js/module/export_named_from_clause.rs +++ b/crates/rome_js_formatter/src/js/module/export_named_from_clause.rs @@ -1,5 +1,5 @@ use crate::prelude::*; -use crate::utils::{node_has_leading_newline, FormatStatementSemicolon}; +use crate::utils::FormatStatementSemicolon; use rome_formatter::write; use rome_js_syntax::JsExportNamedFromClause; @@ -42,7 +42,7 @@ impl FormatNodeRule for FormatJsExportNamedFromClause { write!(f, [space()])?; } _ => { - if node_has_leading_newline(specifiers.syntax()) { + if specifiers.syntax().has_leading_newline() { write!(f, [block_indent(&specifiers.format()),])?; } else { write!( diff --git a/crates/rome_js_formatter/src/utils/mod.rs b/crates/rome_js_formatter/src/utils/mod.rs index 09f84794e17..3134a1fafb2 100644 --- a/crates/rome_js_formatter/src/utils/mod.rs +++ b/crates/rome_js_formatter/src/utils/mod.rs @@ -33,10 +33,10 @@ pub(crate) use conditional::{AnyJsConditional, ConditionalJsxChain}; pub(crate) use object_like::JsObjectLike; pub(crate) use object_pattern_like::JsObjectPatternLike; use rome_formatter::{format_args, write, Buffer}; +use rome_js_syntax::JsSyntaxToken; use rome_js_syntax::{ AnyJsExpression, AnyJsStatement, JsCallExpression, JsInitializerClause, JsLanguage, Modifiers, }; -use rome_js_syntax::{JsSyntaxNode, JsSyntaxToken}; use rome_rowan::{AstNode, AstNodeList}; pub(crate) use string_utils::*; pub(crate) use typescript::{ @@ -142,18 +142,6 @@ impl Format for FormatInterpreterToken<'_> { } } -/// Returns true if this node contains newlines in trivias. -pub(crate) fn node_has_leading_newline(node: &JsSyntaxNode) -> bool { - if let Some(leading_trivia) = node.first_leading_trivia() { - for piece in leading_trivia.pieces() { - if piece.is_newline() { - return true; - } - } - } - false -} - /// Formats the body of a statement where it can either be a single statement, an empty statement, /// or a block statement. pub(crate) struct FormatStatementBody<'a> { diff --git a/crates/rome_js_formatter/src/utils/object_like.rs b/crates/rome_js_formatter/src/utils/object_like.rs index c1bc70da9a6..c636aa8dea6 100644 --- a/crates/rome_js_formatter/src/utils/object_like.rs +++ b/crates/rome_js_formatter/src/utils/object_like.rs @@ -1,5 +1,4 @@ use crate::prelude::*; -use crate::utils::node_has_leading_newline; use crate::JsFormatContext; use rome_formatter::write; use rome_formatter::{Format, FormatResult}; @@ -25,8 +24,8 @@ impl JsObjectLike { fn members_have_leading_newline(&self) -> bool { match self { - JsObjectLike::JsObjectExpression(oe) => node_has_leading_newline(oe.members().syntax()), - JsObjectLike::TsObjectType(ot) => node_has_leading_newline(ot.members().syntax()), + JsObjectLike::JsObjectExpression(oe) => oe.members().syntax().has_leading_newline(), + JsObjectLike::TsObjectType(ot) => ot.members().syntax().has_leading_newline(), } } diff --git a/crates/rome_json_formatter/src/json/auxiliary/member.rs b/crates/rome_json_formatter/src/json/auxiliary/member.rs index fd336f3378b..9f7ab356084 100644 --- a/crates/rome_json_formatter/src/json/auxiliary/member.rs +++ b/crates/rome_json_formatter/src/json/auxiliary/member.rs @@ -1,12 +1,20 @@ use crate::prelude::*; +use rome_formatter::{format_args, write}; use rome_json_syntax::JsonMember; -use rome_rowan::AstNode; #[derive(Debug, Clone, Default)] pub(crate) struct FormatJsonMember; impl FormatNodeRule for FormatJsonMember { fn fmt_fields(&self, node: &JsonMember, f: &mut JsonFormatter) -> FormatResult<()> { - format_verbatim_node(node.syntax()).fmt(f) + write!( + f, + [group(&format_args![ + &node.name().format(), + node.colon_token().format(), + space(), + node.value().format() + ])] + ) } } diff --git a/crates/rome_json_formatter/src/json/lists/member_list.rs b/crates/rome_json_formatter/src/json/lists/member_list.rs index e8d5e3f8955..0cc793b8f7f 100644 --- a/crates/rome_json_formatter/src/json/lists/member_list.rs +++ b/crates/rome_json_formatter/src/json/lists/member_list.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +use crate::separated::FormatAstSeparatedListExtension; use rome_json_syntax::JsonMemberList; +use rome_rowan::{AstNode, AstSeparatedList}; #[derive(Debug, Clone, Default)] pub(crate) struct FormatJsonMemberList; @@ -7,6 +9,12 @@ pub(crate) struct FormatJsonMemberList; impl FormatRule for FormatJsonMemberList { type Context = JsonFormatContext; fn fmt(&self, node: &JsonMemberList, f: &mut JsonFormatter) -> FormatResult<()> { - format_verbatim_node(node.syntax()).fmt(f) + let mut join = f.join_nodes_with_soft_line(); + + for (element, formatted) in node.elements().zip(node.format_separated(",")) { + join.entry(element.node()?.syntax(), &formatted); + } + + join.finish() } } diff --git a/crates/rome_json_formatter/src/json/value/object_value.rs b/crates/rome_json_formatter/src/json/value/object_value.rs index 7ab45d2b2bf..b2e4481d0a7 100644 --- a/crates/rome_json_formatter/src/json/value/object_value.rs +++ b/crates/rome_json_formatter/src/json/value/object_value.rs @@ -1,4 +1,5 @@ use crate::prelude::*; +use rome_formatter::write; use rome_json_syntax::JsonObjectValue; use rome_rowan::AstNode; @@ -7,6 +8,18 @@ pub(crate) struct FormatJsonObjectValue; impl FormatNodeRule for FormatJsonObjectValue { fn fmt_fields(&self, node: &JsonObjectValue, f: &mut JsonFormatter) -> FormatResult<()> { - format_verbatim_node(node.syntax()).fmt(f) + write!(f, [node.l_curly_token().format(),])?; + + let should_expand = node.json_member_list().syntax().has_leading_newline(); + + write!( + f, + [group(&soft_space_or_block_indent( + &node.json_member_list().format() + )) + .should_expand(should_expand)] + )?; + + write!(f, [node.r_curly_token().format()]) } } diff --git a/crates/rome_json_formatter/src/lib.rs b/crates/rome_json_formatter/src/lib.rs index b23caa20f4e..b41fb66683b 100644 --- a/crates/rome_json_formatter/src/lib.rs +++ b/crates/rome_json_formatter/src/lib.rs @@ -3,6 +3,7 @@ mod cst; mod generated; mod json; mod prelude; +mod separated; pub(crate) use crate::context::JsonFormatContext; use crate::context::JsonFormatOptions; @@ -170,21 +171,10 @@ mod tests { "#; let parse = parse_json(src, FileId::zero()); let options = JsonFormatOptions::default(); - let result = format_node(options, &parse.syntax()) - .unwrap() - .print() - .unwrap(); - + let formatted = format_node(options, &parse.syntax()).unwrap(); assert_eq!( - result.as_code(), - r#"{ - "a": 5, - "b": [1, 2, 3, 4], - "c": null, - "d": true, - "e": false -} -"# + formatted.print().unwrap().as_code(), + "{\n\t\"a\": 5,\n\t\"b\": [1, 2, 3, 4],\n\t\"c\": null,\n\t\"d\": true,\n\t\"e\": false\n}\n" ); } } diff --git a/crates/rome_json_formatter/src/separated.rs b/crates/rome_json_formatter/src/separated.rs new file mode 100644 index 00000000000..82cb93f7175 --- /dev/null +++ b/crates/rome_json_formatter/src/separated.rs @@ -0,0 +1,159 @@ +use crate::prelude::*; +use crate::AsFormat; +use rome_formatter::{write, GroupId}; +use rome_json_syntax::JsonLanguage; +use rome_rowan::{ + AstNode, AstSeparatedElement, AstSeparatedList, AstSeparatedListElementsIterator, Language, + SyntaxResult, +}; +use std::iter::FusedIterator; + +/// Formats a single element inside of a separated list. +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct FormatSeparatedElement { + element: AstSeparatedElement, + is_last: bool, + /// The separator to write if the element has no separator yet. + separator: &'static str, + options: FormatSeparatedOptions, +} + +impl> FormatSeparatedElement { + /// Returns the node belonging to the element. + #[allow(unused)] + pub fn node(&self) -> SyntaxResult<&N> { + self.element.node() + } +} + +impl Format for FormatSeparatedElement +where + N: AstNode + AsFormat, +{ + fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { + let node = self.element.node()?; + let separator = self.element.trailing_separator()?; + + if !self.options.nodes_grouped { + node.format().fmt(f)?; + } else { + group(&node.format()).fmt(f)?; + } + + // Reuse the existing trailing separator or create it if it wasn't in the + // input source. Only print the last trailing token if the outer group breaks + if let Some(separator) = separator { + if self.is_last { + return Err(FormatError::SyntaxError); + } else { + write!(f, [separator.format()])?; + } + } else if self.is_last { + /* no op */ + } else { + unreachable!( + "This is a syntax error, separator must be present between every two elements" + ); + }; + + Ok(()) + } +} + +/// Iterator for formatting separated elements. Prints the separator between each element and +/// inserts a trailing separator if necessary +pub struct FormatSeparatedIter +where + Language: rome_rowan::Language, +{ + next: Option>, + inner: I, + separator: &'static str, + options: FormatSeparatedOptions, +} + +impl FormatSeparatedIter +where + L: Language, +{ + fn new(inner: I, separator: &'static str) -> Self { + Self { + inner, + separator, + next: None, + options: FormatSeparatedOptions::default(), + } + } + + /// Wraps every node inside of a group + #[allow(unused)] + pub fn nodes_grouped(mut self) -> Self { + self.options.nodes_grouped = true; + self + } + + #[allow(unused)] + pub fn with_group_id(mut self, group_id: Option) -> Self { + self.options.group_id = group_id; + self + } +} + +impl Iterator for FormatSeparatedIter +where + I: Iterator>, +{ + type Item = FormatSeparatedElement; + + fn next(&mut self) -> Option { + let element = self.next.take().or_else(|| self.inner.next())?; + + self.next = self.inner.next(); + let is_last = self.next.is_none(); + + Some(FormatSeparatedElement { + element, + is_last, + separator: self.separator, + options: self.options, + }) + } +} + +impl FusedIterator for FormatSeparatedIter where + I: Iterator> + FusedIterator +{ +} + +impl ExactSizeIterator for FormatSeparatedIter where + I: Iterator> + ExactSizeIterator +{ +} + +/// AST Separated list formatting extension methods +pub trait FormatAstSeparatedListExtension: AstSeparatedList { + /// Prints a separated list of nodes + /// + /// Trailing separators will be reused from the original list or + /// created by calling the `separator_factory` function. + /// The last trailing separator in the list will only be printed + /// if the outer group breaks. + fn format_separated( + &self, + separator: &'static str, + ) -> FormatSeparatedIter< + AstSeparatedListElementsIterator, + JsonLanguage, + Self::Node, + > { + FormatSeparatedIter::new(self.elements(), separator) + } +} + +impl FormatAstSeparatedListExtension for T where T: AstSeparatedList {} + +#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)] +pub struct FormatSeparatedOptions { + group_id: Option, + nodes_grouped: bool, +} diff --git a/crates/rome_json_formatter/tests/specs/json/object/complex.json b/crates/rome_json_formatter/tests/specs/json/object/complex.json new file mode 100644 index 00000000000..86c5926eca3 --- /dev/null +++ b/crates/rome_json_formatter/tests/specs/json/object/complex.json @@ -0,0 +1,7 @@ +{ + "number": 1123123213123123123123122311231232131231231231231223, + "string": "some-long-long-long-long-long-long-long-string", + "array": [12312321, {"another-number": 12321321, "string": "some-string"}], + "object": {"array": [123214123, "some-long-long-string", [12312312, "some-long-long-string"]]}, + "null": null +} diff --git a/crates/rome_json_formatter/tests/specs/json/object/complex.json.snap b/crates/rome_json_formatter/tests/specs/json/object/complex.json.snap new file mode 100644 index 00000000000..55fc77f04a6 --- /dev/null +++ b/crates/rome_json_formatter/tests/specs/json/object/complex.json.snap @@ -0,0 +1,54 @@ +--- +source: crates/rome_formatter_test/src/snapshot_builder.rs +info: json/object/complex.json +--- + +# Input + +```json +{ + "number": 1123123213123123123123122311231232131231231231231223, + "string": "some-long-long-long-long-long-long-long-string", + "array": [12312321, {"another-number": 12321321, "string": "some-string"}], + "object": {"array": [123214123, "some-long-long-string", [12312312, "some-long-long-string"]]}, + "null": null +} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Line width: 80 +----- + +```json +{ + "number": 1123123213123123123123122311231232131231231231231223, + "string": "some-long-long-long-long-long-long-long-string", + "array": [12312321, {"another-number": 12321321, "string": "some-string"}], + "object": { + "array": [123214123, "some-long-long-string", [12312312, "some-long-long-string"]] + }, + "null": null +} +``` + + + +## Unimplemented nodes/tokens + +" [12312321, {\"another-number\": 12321321, \"string\": \"some-string\"}" => 137..202 +" [123214123, \"some-long-long-string\", [12312312, \"some-long-long-string\"]" => 228..301 +# Lines exceeding max width of 80 characters +``` + 6: "array": [123214123, "some-long-long-string", [12312312, "some-long-long-string"]] +``` + + diff --git a/crates/rome_json_formatter/tests/specs/json/object/multi_line.json b/crates/rome_json_formatter/tests/specs/json/object/multi_line.json new file mode 100644 index 00000000000..ac178a4f731 --- /dev/null +++ b/crates/rome_json_formatter/tests/specs/json/object/multi_line.json @@ -0,0 +1,4 @@ +{ + "number": 123, + "string": "some-string" +} diff --git a/crates/rome_json_formatter/tests/specs/json/object/multi_line.json.snap b/crates/rome_json_formatter/tests/specs/json/object/multi_line.json.snap new file mode 100644 index 00000000000..74b486fee2e --- /dev/null +++ b/crates/rome_json_formatter/tests/specs/json/object/multi_line.json.snap @@ -0,0 +1,35 @@ +--- +source: crates/rome_formatter_test/src/snapshot_builder.rs +info: json/object/multi_line.json +--- + +# Input + +```json +{ + "number": 123, + "string": "some-string" +} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Line width: 80 +----- + +```json +{ + "number": 123, + "string": "some-string" +} +``` + + diff --git a/crates/rome_json_formatter/tests/specs/json/object/multi_line_long.json b/crates/rome_json_formatter/tests/specs/json/object/multi_line_long.json new file mode 100644 index 00000000000..cc077bf188d --- /dev/null +++ b/crates/rome_json_formatter/tests/specs/json/object/multi_line_long.json @@ -0,0 +1,4 @@ +{ + "number": 1123123213123123123123122311231232131231231231231223, + "string": "some-long-long-long-long-long-long-long-string" +} diff --git a/crates/rome_json_formatter/tests/specs/json/object/multi_line_long.json.snap b/crates/rome_json_formatter/tests/specs/json/object/multi_line_long.json.snap new file mode 100644 index 00000000000..f5b40bf2e18 --- /dev/null +++ b/crates/rome_json_formatter/tests/specs/json/object/multi_line_long.json.snap @@ -0,0 +1,35 @@ +--- +source: crates/rome_formatter_test/src/snapshot_builder.rs +info: json/object/multi_line_long.json +--- + +# Input + +```json +{ + "number": 1123123213123123123123122311231232131231231231231223, + "string": "some-long-long-long-long-long-long-long-string" +} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Line width: 80 +----- + +```json +{ + "number": 1123123213123123123123122311231232131231231231231223, + "string": "some-long-long-long-long-long-long-long-string" +} +``` + + diff --git a/crates/rome_json_formatter/tests/specs/json/object/one_line.json b/crates/rome_json_formatter/tests/specs/json/object/one_line.json new file mode 100644 index 00000000000..d49a5b7fb59 --- /dev/null +++ b/crates/rome_json_formatter/tests/specs/json/object/one_line.json @@ -0,0 +1 @@ +{"number": 123, "string": "some-string"} diff --git a/crates/rome_json_formatter/tests/specs/json/object/one_line.json.snap b/crates/rome_json_formatter/tests/specs/json/object/one_line.json.snap new file mode 100644 index 00000000000..2bd064b8175 --- /dev/null +++ b/crates/rome_json_formatter/tests/specs/json/object/one_line.json.snap @@ -0,0 +1,29 @@ +--- +source: crates/rome_formatter_test/src/snapshot_builder.rs +info: json/object/one_line.json +--- + +# Input + +```json +{"number": 123, "string": "some-string"} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Line width: 80 +----- + +```json +{ "number": 123, "string": "some-string" } +``` + + diff --git a/crates/rome_json_formatter/tests/specs/json/object/one_line_long.json b/crates/rome_json_formatter/tests/specs/json/object/one_line_long.json new file mode 100644 index 00000000000..a57f16f0123 --- /dev/null +++ b/crates/rome_json_formatter/tests/specs/json/object/one_line_long.json @@ -0,0 +1 @@ +{"number": 1123123213123123123123122311231232131231231231231223, "string": "some-long-long-long-long-long-long-long-string"} diff --git a/crates/rome_json_formatter/tests/specs/json/object/one_line_long.json.snap b/crates/rome_json_formatter/tests/specs/json/object/one_line_long.json.snap new file mode 100644 index 00000000000..6d708f8c4ff --- /dev/null +++ b/crates/rome_json_formatter/tests/specs/json/object/one_line_long.json.snap @@ -0,0 +1,32 @@ +--- +source: crates/rome_formatter_test/src/snapshot_builder.rs +info: json/object/one_line_long.json +--- + +# Input + +```json +{"number": 1123123213123123123123122311231232131231231231231223, "string": "some-long-long-long-long-long-long-long-string"} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Line width: 80 +----- + +```json +{ + "number": 1123123213123123123123122311231232131231231231231223, + "string": "some-long-long-long-long-long-long-long-string" +} +``` + + diff --git a/crates/rome_json_formatter/tests/specs/json/smoke.json.snap b/crates/rome_json_formatter/tests/specs/json/smoke.json.snap index 31afddae28c..b1b6e92d2e9 100644 --- a/crates/rome_json_formatter/tests/specs/json/smoke.json.snap +++ b/crates/rome_json_formatter/tests/specs/json/smoke.json.snap @@ -1,7 +1,6 @@ --- source: crates/rome_formatter_test/src/snapshot_builder.rs -info: - test_file: json/smoke.json +info: json/smoke.json --- # Input @@ -43,5 +42,5 @@ Line width: 80 ## Unimplemented nodes/tokens -"{\n\t\"a\": 5,\n\t\"b\": [1, 2, 3, 4],\n\t\"c\": null,\n\t\"d\": true,\n\t\"e\": false\n}" => 0..68 +" [1, 2, 3, 4" => 16..28 diff --git a/crates/rome_json_formatter/tests/specs/prettier/json/json/key-value.json.snap b/crates/rome_json_formatter/tests/specs/prettier/json/json/key-value.json.snap deleted file mode 100644 index d975c1a04e8..00000000000 --- a/crates/rome_json_formatter/tests/specs/prettier/json/json/key-value.json.snap +++ /dev/null @@ -1,52 +0,0 @@ ---- -source: crates/rome_formatter_test/src/snapshot_builder.rs -info: - test_file: json/json/key-value.json ---- - -# Input - -```json -{ - "string": "stringstringstringstringstringstringstringstringstringstringstringstringstringstringstring", - "stringstringstringstringstringstringstringstring": "stringstringstringstringstringstringstringstring", - "stringstringstringstringstringstringstringstringstringstringstringstringstringstringstring": "string" -} - -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,5 +1,5 @@ - { -- "string": "stringstringstringstringstringstringstringstringstringstringstringstringstringstringstring", -- "stringstringstringstringstringstringstringstring": "stringstringstringstringstringstringstringstring", -- "stringstringstringstringstringstringstringstringstringstringstringstringstringstringstring": "string" -+ "string": "stringstringstringstringstringstringstringstringstringstringstringstringstringstringstring", -+ "stringstringstringstringstringstringstringstring": "stringstringstringstringstringstringstringstring", -+ "stringstringstringstringstringstringstringstringstringstringstringstringstringstringstring": "string" - } -``` - -# Output - -```json -{ - "string": "stringstringstringstringstringstringstringstringstringstringstringstringstringstringstring", - "stringstringstringstringstringstringstringstring": "stringstringstringstringstringstringstringstring", - "stringstringstringstringstringstringstringstringstringstringstringstringstringstringstring": "string" -} -``` - -# Lines exceeding max width of 80 characters -``` - 2: "string": "stringstringstringstringstringstringstringstringstringstringstringstringstringstringstring", - 3: "stringstringstringstringstringstringstringstring": "stringstringstringstringstringstringstringstring", - 4: "stringstringstringstringstringstringstringstringstringstringstringstringstringstringstring": "string" -``` - - diff --git a/crates/rome_json_formatter/tests/specs/prettier/json/json/multi-line.json.snap b/crates/rome_json_formatter/tests/specs/prettier/json/json/multi-line.json.snap index bde4eabf968..69ec45d5d53 100644 --- a/crates/rome_json_formatter/tests/specs/prettier/json/json/multi-line.json.snap +++ b/crates/rome_json_formatter/tests/specs/prettier/json/json/multi-line.json.snap @@ -1,7 +1,6 @@ --- source: crates/rome_formatter_test/src/snapshot_builder.rs -info: - test_file: json/json/multi-line.json +info: json/json/multi-line.json --- # Input @@ -18,17 +17,27 @@ info: ```diff --- Prettier +++ Rome -@@ -1 +1,2 @@ +@@ -1 +1,7 @@ -{ "key1": [true, false, null], "key2": { "key3": [1, 2, "3", 1e10, 1e-3] } } -+{"key1":[true,false,null],"key2":{"key3":[1,2,"3", -+1e10,1e-3]}} ++{ ++ "key1": [true,false,null], ++ "key2": { ++ "key3": [1,2,"3", ++1e10,1e-3] ++ } ++} ``` # Output ```json -{"key1":[true,false,null],"key2":{"key3":[1,2,"3", -1e10,1e-3]}} +{ + "key1": [true,false,null], + "key2": { + "key3": [1,2,"3", +1e10,1e-3] + } +} ``` diff --git a/crates/rome_json_formatter/tests/specs/prettier/json/json/single-line.json.snap b/crates/rome_json_formatter/tests/specs/prettier/json/json/single-line.json.snap index 67364384ef8..c7cb526c5d7 100644 --- a/crates/rome_json_formatter/tests/specs/prettier/json/json/single-line.json.snap +++ b/crates/rome_json_formatter/tests/specs/prettier/json/json/single-line.json.snap @@ -1,7 +1,6 @@ --- source: crates/rome_formatter_test/src/snapshot_builder.rs -info: - test_file: json/json/single-line.json +info: json/json/single-line.json --- # Input @@ -19,13 +18,13 @@ info: +++ Rome @@ -1 +1 @@ -{ "key1": [true, false, null], "key2": { "key3": [1, 2, "3", 1e10, 1e-3] } } -+{"key1":[true,false,null],"key2":{"key3":[1,2,"3",1e10,1e-3]}} ++{ "key1": [true,false,null], "key2": { "key3": [1,2,"3",1e10,1e-3] } } ``` # Output ```json -{"key1":[true,false,null],"key2":{"key3":[1,2,"3",1e10,1e-3]}} +{ "key1": [true,false,null], "key2": { "key3": [1,2,"3",1e10,1e-3] } } ``` diff --git a/crates/rome_json_formatter/tests/specs/prettier/json/range/identifier.json.snap b/crates/rome_json_formatter/tests/specs/prettier/json/range/identifier.json.snap deleted file mode 100644 index 35485139381..00000000000 --- a/crates/rome_json_formatter/tests/specs/prettier/json/range/identifier.json.snap +++ /dev/null @@ -1,31 +0,0 @@ ---- -source: crates/rome_formatter_test/src/snapshot_builder.rs -info: - test_file: json/range/identifier.json ---- - -# Input - -```json -{"a":1, "b":2} - -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1 +1 @@ --{ "a": 1, "b": 2 } -+{"a":1, "b":2} -``` - -# Output - -```json -{"a":1, "b":2} -``` - - diff --git a/crates/rome_json_formatter/tests/specs/prettier/json/range/inside-object.json.snap b/crates/rome_json_formatter/tests/specs/prettier/json/range/inside-object.json.snap index 01d387af913..542df34c994 100644 --- a/crates/rome_json_formatter/tests/specs/prettier/json/range/inside-object.json.snap +++ b/crates/rome_json_formatter/tests/specs/prettier/json/range/inside-object.json.snap @@ -1,7 +1,6 @@ --- source: crates/rome_formatter_test/src/snapshot_builder.rs -info: - test_file: json/range/inside-object.json +info: json/range/inside-object.json --- # Input @@ -20,10 +19,11 @@ b: {d:4} ```diff --- Prettier +++ Rome -@@ -1 +1,4 @@ +@@ -1 +1,5 @@ -{ "a": { "b": 2, "c": 3 }, "b": { "d": 4 } } +{a: -+{ "b": 2, "c": 3 }, ++{ "b": 2, ++"c": 3 }, +b: {d:4} +} ``` @@ -32,7 +32,8 @@ b: {d:4} ```json {a: -{ "b": 2, "c": 3 }, +{ "b": 2, +"c": 3 }, b: {d:4} } ``` diff --git a/crates/rome_json_formatter/tests/specs/prettier/json/range/issue-4009.json.snap b/crates/rome_json_formatter/tests/specs/prettier/json/range/issue-4009.json.snap deleted file mode 100644 index 57f7a72c3f3..00000000000 --- a/crates/rome_json_formatter/tests/specs/prettier/json/range/issue-4009.json.snap +++ /dev/null @@ -1,37 +0,0 @@ ---- -source: crates/rome_formatter_test/src/snapshot_builder.rs -info: - test_file: json/range/issue-4009.json ---- - -# Input - -```json -{ - "foo": "bar" -} - -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,3 +1,3 @@ - { -- "foo": "bar" -+ "foo": "bar" - } -``` - -# Output - -```json -{ - "foo": "bar" -} -``` - - diff --git a/crates/rome_json_formatter/tests/specs/prettier/json/range/issue-7116.json.snap b/crates/rome_json_formatter/tests/specs/prettier/json/range/number.json.snap similarity index 58% rename from crates/rome_json_formatter/tests/specs/prettier/json/range/issue-7116.json.snap rename to crates/rome_json_formatter/tests/specs/prettier/json/range/number.json.snap index 1de5be4695f..4c1cbbd5b49 100644 --- a/crates/rome_json_formatter/tests/specs/prettier/json/range/issue-7116.json.snap +++ b/crates/rome_json_formatter/tests/specs/prettier/json/range/number.json.snap @@ -1,13 +1,12 @@ --- source: crates/rome_formatter_test/src/snapshot_builder.rs -info: - test_file: json/range/issue-7116.json +info: json/range/number.json --- # Input ```json -{"b": 2} +{ "b": 2, "c": 3 } ``` @@ -17,15 +16,17 @@ info: ```diff --- Prettier +++ Rome -@@ -1 +1 @@ --{ "b": 2 } -+{"b": 2} +@@ -1 +1,2 @@ +-{ "b": 2, "c": 3 } ++{ "b": 2, ++"c": 3 } ``` # Output ```json -{"b": 2} +{ "b": 2, +"c": 3 } ``` diff --git a/crates/rome_rowan/src/syntax/node.rs b/crates/rome_rowan/src/syntax/node.rs index ea1a2e6054e..bf6dee1ad4f 100644 --- a/crates/rome_rowan/src/syntax/node.rs +++ b/crates/rome_rowan/src/syntax/node.rs @@ -500,6 +500,12 @@ impl SyntaxNode { self.first_token() .map_or(false, |tok| tok.has_leading_comments()) } + + /// Whether the node contains leading newlines. + pub fn has_leading_newline(&self) -> bool { + self.first_token() + .map_or(false, |tok| tok.has_leading_newline()) + } } impl SyntaxNode diff --git a/crates/rome_rowan/src/syntax/token.rs b/crates/rome_rowan/src/syntax/token.rs index 9c266c40b5d..45df9f66d7b 100644 --- a/crates/rome_rowan/src/syntax/token.rs +++ b/crates/rome_rowan/src/syntax/token.rs @@ -378,6 +378,13 @@ impl SyntaxToken { .pieces() .any(|piece| piece.is_whitespace() || piece.is_newline()) } + + /// Checks if the current token has leading newline + pub fn has_leading_newline(&self) -> bool { + self.leading_trivia() + .pieces() + .any(|piece| piece.is_newline()) + } } impl fmt::Debug for SyntaxToken {