Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

feat(rome_formatter): add support to format comments #4718

Merged
merged 26 commits into from
Jul 21, 2023
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
216773f
feat: 🎸 allow comments in json file
IWANABETHATGUY Apr 17, 2023
62527a6
chore: 🤖 fmt
IWANABETHATGUY Apr 17, 2023
091b957
chore: 🤖 update schema
IWANABETHATGUY Apr 17, 2023
a50910e
chore: 🤖 lint
IWANABETHATGUY Apr 17, 2023
77939fa
chore: 🤖 update codegen
IWANABETHATGUY Apr 22, 2023
9e5d51f
chore: 🤖 pass all tests
IWANABETHATGUY May 3, 2023
8a2531e
chore: 🤖 basic finish parse with comments
IWANABETHATGUY May 3, 2023
43c655d
chore: 🤖 format
IWANABETHATGUY May 4, 2023
b816d45
chore: 🤖 lint
IWANABETHATGUY May 4, 2023
584e045
fix: 🐛 compile erorr
IWANABETHATGUY May 4, 2023
7fc1bec
chore: 🤖 add matcher
IWANABETHATGUY May 5, 2023
a55484f
chore: 🤖 add extra test
IWANABETHATGUY May 5, 2023
872b164
chore: 🤖 update snap
IWANABETHATGUY May 5, 2023
4e2ef9b
chore: 🤖 update snap
IWANABETHATGUY May 5, 2023
94d581b
chore: 🤖 basic finish
IWANABETHATGUY May 5, 2023
955fca0
fix Cargo.toml
ematipico Jul 20, 2023
228ed45
chore: rebase
ematipico Jul 20, 2023
d172dac
chore: rebase
ematipico Jul 20, 2023
a8b520d
just ready
ematipico Jul 20, 2023
3f0240d
feat(rome_formatter): add support to format comments
ematipico Jul 20, 2023
f299ba5
Merge remote-tracking branch 'origin/main' into feat/formatter-json-c…
ematipico Jul 20, 2023
d3e0f32
chore: add proper comments
ematipico Jul 21, 2023
91a535c
update changelog
ematipico Jul 21, 2023
ad2eaec
refactor
ematipico Jul 21, 2023
7b6f93a
update playground
ematipico Jul 21, 2023
71a71f8
regression
ematipico Jul 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,18 @@ if no error diagnostics are emitted.
rome check --error-on-wanrings ./src
```

- Add a configuration to enable parsing comments inside JSON files:

```json
{
"json": {
"parser": {
"allowComments": true
}
}
}
```

### Editors

#### Other changes
Expand All @@ -99,9 +111,11 @@ if no error diagnostics are emitted.

### Formatter

- Added a new option called `--jsx-quote-style` to the formatter. This option allows you to choose between single and double quotes for JSX attributes. [#4486](https://github.com/rome/tools/issues/4486)
- Add a new option called `--jsx-quote-style` to the formatter. This option allows you to choose between single and double quotes for JSX attributes. [#4486](https://github.com/rome/tools/issues/4486)

- Added a new option called `--arrow-parentheses` to the formatter. This option allows you to set the parentheses style for arrow functions. [#4666](https://github.com/rome/tools/issues/4666)
- Add a new option called `--arrow-parentheses` to the formatter. This option allows you to set the parentheses style for arrow functions. [#4666](https://github.com/rome/tools/issues/4666)

- The JSON formatter is now able to format `.json` files that have comments.

### Linter

Expand Down Expand Up @@ -345,7 +359,17 @@ if no error diagnostics are emitted.
}
}
```
- Add for parsing comments inside JSON files:

```json
{
"json": {
"parser": {
"allowComments": true
}
}
}
```
### VSCode

### JavaScript APIs
Expand Down
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ rome_rowan = { version = "0.0.1", path = "./crates/rome_rowan"
rome_service = { path = "./crates/rome_service" }
rome_text_edit = { version = "0.0.1", path = "./crates/rome_text_edit" }
rome_text_size = { version = "0.0.1", path = "./crates/rome_text_size" }
rome_suppression = { version = "0.0.1", path = "./crates/rome_suppression" }
tests_macros = { path = "./crates/tests_macros" }

# Crates needed in the workspace
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,21 @@ expression: content

/*test*/ [1, 2, 3]

```

# Termination Message

```block
internalError/io ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× No files were processed in the specified paths.



```

# Emitted Messages

```block
tsconfig.json format ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× Format with errors is disabled.
i Formatter would have printed the following content:

1 │ -
2 │ - /*test*/·[1,·2,·3]
3 │ - →
1 │ + /*test*/
2 │ + [1,·2,·3]
3 │ +


```
Expand All @@ -45,8 +41,4 @@ tsconfig.json format ━━━━━━━━━━━━━━━━━━━
Compared 1 file(s) in <TIME>
```

```block
Skipped 1 file(s)
```


1 change: 1 addition & 0 deletions crates/rome_formatter_test/src/check_reformat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ where
.language
.format_node(self.options.clone(), &re_parse.syntax())
.unwrap();
println!("{}", &formatted.document());
ematipico marked this conversation as resolved.
Show resolved Hide resolved
let printed = formatted.print().unwrap();

if self.text != printed.as_code() {
Expand Down
2 changes: 1 addition & 1 deletion crates/rome_js_formatter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
//! It helps you to understand which nodes need to be implemented/modified
//! in order to implement formatting. Alternatively, you can locally run the playground by following
//! the [playground instructions](https://github.com/rome/tools/blob/main/website/playground/README.md).
//! 5. Use the [`quick_test()`](https://github.com/rome/tools/blob/main/crates/rome_js_formatter/src/lib.rs#L597-L616)
//! 5. Use the `quick_test.rs` file in `tests/` directory.
//! function to test you snippet straight from your IDE, without running the whole test suite. The test
//! is ignored on purpose, so you won't need to worry about the CI breaking.
//!
Expand Down
1 change: 0 additions & 1 deletion crates/rome_js_formatter/tests/quick_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ fn quick_test() {
syntax,
JsParserOptions::default().with_parse_class_parameter_decorators(),
);
dbg!(tree.syntax());
let options = JsFormatOptions::new(syntax)
.with_semicolons(Semicolons::Always)
.with_quote_style(QuoteStyle::Double)
Expand Down
3 changes: 2 additions & 1 deletion crates/rome_json_formatter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ version = "0.0.1"
rome_formatter = { workspace = true }
rome_json_syntax = { workspace = true }
rome_rowan = { workspace = true }
rome_diagnostics = { workspace = true }
rome_suppression = { workspace = true }

[dev-dependencies]
countme = { workspace = true, features = ["enable"] }
insta = { workspace = true, features = ["glob"] }
rome_diagnostics = { workspace = true }
rome_formatter_test = { workspace = true }
rome_fs = { workspace = true }
rome_json_factory = { workspace = true }
Expand Down
79 changes: 79 additions & 0 deletions crates/rome_json_formatter/src/comments.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use crate::prelude::*;
use rome_diagnostics::category;
use rome_formatter::comments::{CommentKind, CommentStyle, Comments, SourceComment};
use rome_formatter::formatter::Formatter;
use rome_formatter::{write, FormatResult, FormatRule};
use rome_json_syntax::{JsonLanguage, TextLen};
use rome_rowan::SyntaxTriviaPieceComments;
use rome_suppression::parse_suppression_comment;

pub type JsonComments = Comments<JsonLanguage>;

#[derive(Default)]
pub struct FormatJsonLeadingComment;

impl FormatRule<SourceComment<JsonLanguage>> for FormatJsonLeadingComment {
type Context = JsonFormatContext;

fn fmt(
&self,
comment: &SourceComment<JsonLanguage>,
f: &mut Formatter<Self::Context>,
) -> FormatResult<()> {
let mut source_offset = comment.piece().text_range().start();

let mut lines = comment.piece().text().lines();

// SAFETY: Safe, `is_doc_comment` only returns `true` for multiline comments
ematipico marked this conversation as resolved.
Show resolved Hide resolved
let first_line = lines.next().unwrap();
write!(f, [dynamic_text(first_line.trim_end(), source_offset)])?;

source_offset += first_line.text_len();

// Indent the remaining lines by one space so that all `*` are aligned.
write!(
f,
[align(
1,
&format_once(|f| {
for line in lines {
write!(
f,
[hard_line_break(), dynamic_text(line.trim(), source_offset)]
)?;

source_offset += line.text_len();
}

Ok(())
})
)]
)
}
}

#[derive(Eq, PartialEq, Copy, Clone, Debug, Default)]
pub struct JsonCommentStyle;

impl CommentStyle for JsonCommentStyle {
type Language = JsonLanguage;

fn is_suppression(text: &str) -> bool {
parse_suppression_comment(text)
.filter_map(Result::ok)
.flat_map(|suppression| suppression.categories)
.any(|(key, _)| key == category!("format"))
}

fn get_comment_kind(comment: &SyntaxTriviaPieceComments<Self::Language>) -> CommentKind {
if comment.text().starts_with("/*") {
if comment.has_newline() {
CommentKind::Block
} else {
CommentKind::InlineBlock
}
} else {
CommentKind::Line
}
}
}
20 changes: 15 additions & 5 deletions crates/rome_json_formatter/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,33 @@ use rome_formatter::{
CstFormatContext, FormatContext, FormatOptions, IndentStyle, LineWidth, TransformSourceMap,
};

use crate::comments::{FormatJsonLeadingComment, JsonComments};
use rome_formatter::comments::{Comments, FormatPlainComment};
use rome_json_syntax::JsonLanguage;
use std::fmt;
use std::rc::Rc;

#[derive(Debug)]
pub struct JsonFormatContext {
options: JsonFormatOptions,
comments: Comments<JsonLanguage>,
/// The comments of the nodes and tokens in the program.
comments: Rc<JsonComments>,
source_map: Option<TransformSourceMap>,
}

impl JsonFormatContext {
pub fn new(options: JsonFormatOptions) -> Self {
pub fn new(options: JsonFormatOptions, comments: JsonComments) -> Self {
Self {
options,
comments: Comments::default(),
comments: Rc::new(comments),
source_map: None,
}
}

pub fn with_source_map(mut self, source_map: Option<TransformSourceMap>) -> Self {
self.source_map = source_map;
self
}
}

impl FormatContext for JsonFormatContext {
Expand All @@ -38,9 +48,9 @@ impl FormatContext for JsonFormatContext {
impl CstFormatContext for JsonFormatContext {
type Language = JsonLanguage;
type Style = JsonCommentStyle;
type CommentRule = FormatPlainComment<Self>;
type CommentRule = FormatJsonLeadingComment;

fn comments(&self) -> &Comments<Self::Language> {
fn comments(&self) -> &JsonComments {
&self.comments
}
}
Expand Down
47 changes: 36 additions & 11 deletions crates/rome_json_formatter/src/json/value/object_value.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::prelude::*;
use rome_formatter::write;
use rome_formatter::{format_args, write};
use rome_json_syntax::JsonObjectValue;
use rome_rowan::AstNode;

Expand All @@ -8,18 +8,43 @@ pub(crate) struct FormatJsonObjectValue;

impl FormatNodeRule<JsonObjectValue> for FormatJsonObjectValue {
fn fmt_fields(&self, node: &JsonObjectValue, f: &mut JsonFormatter) -> FormatResult<()> {
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)]
)?;
let list = format_with(|f| {
write!(
f,
[group(&soft_space_or_block_indent(
&node.json_member_list().format()
))
.should_expand(should_expand)]
)
});
if f.comments().has_leading_comments(node.syntax()) {
write!(
f,
[
format_leading_comments(node.syntax()),
group(&format_args![
node.l_curly_token().format(),
list,
node.r_curly_token().format()
]),
]
)
} else {
write!(
f,
[
node.l_curly_token().format(),
list,
node.r_curly_token().format()
]
)
}
}

write!(f, [node.r_curly_token().format()])
fn fmt_leading_comments(&self, _: &JsonObjectValue, _: &mut JsonFormatter) -> FormatResult<()> {
// Formatted as part of `fmt_fields`
Ok(())
}
}
Loading
Loading