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

feat(rome_js_formatter): class property members as assignment like #2797

Merged
merged 3 commits into from
Jun 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 5 additions & 25 deletions crates/rome_js_formatter/src/js/classes/property_class_member.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,18 @@
use crate::prelude::*;
use rome_formatter::{format_args, write};

use crate::utils::FormatWithSemicolon;

use crate::utils::{FormatWithSemicolon, JsAnyAssignmentLike};
use rome_formatter::write;
use rome_js_syntax::JsPropertyClassMember;
use rome_js_syntax::JsPropertyClassMemberFields;

#[derive(Debug, Clone, Default)]
pub struct FormatJsPropertyClassMember;

impl FormatNodeRule<JsPropertyClassMember> for FormatJsPropertyClassMember {
fn fmt_fields(&self, node: &JsPropertyClassMember, f: &mut JsFormatter) -> FormatResult<()> {
let JsPropertyClassMemberFields {
modifiers,
name,
property_annotation,
value,
semicolon_token,
} = node.as_fields();

let semicolon_token = node.semicolon_token();
let body = format_with(|f| write!(f, [JsAnyAssignmentLike::from(node.clone())]));
write!(
f,
[FormatWithSemicolon::new(
&format_args!(
modifiers.format(),
space_token(),
name.format(),
property_annotation.format(),
value
.format()
.with_or_empty(|node, f| write![f, [space_token(), node]]),
),
semicolon_token.as_ref()
)]
[FormatWithSemicolon::new(&body, semicolon_token.as_ref())]
)
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use crate::prelude::*;
use rome_formatter::{format_args, write};

use crate::utils::FormatWithSemicolon;

use rome_js_syntax::{TsPropertySignatureClassMember, TsPropertySignatureClassMemberFields};
use crate::utils::{FormatWithSemicolon, JsAnyAssignmentLike};
use rome_formatter::write;
use rome_js_syntax::TsPropertySignatureClassMember;

#[derive(Debug, Clone, Default)]
pub struct FormatTsPropertySignatureClassMember;
Expand All @@ -14,24 +12,11 @@ impl FormatNodeRule<TsPropertySignatureClassMember> for FormatTsPropertySignatur
node: &TsPropertySignatureClassMember,
f: &mut JsFormatter,
) -> FormatResult<()> {
let TsPropertySignatureClassMemberFields {
modifiers,
name,
property_annotation,
semicolon_token,
} = node.as_fields();

let semicolon_token = node.semicolon_token();
let body = format_with(|f| write!(f, [JsAnyAssignmentLike::from(node.clone())]));
write!(
f,
[FormatWithSemicolon::new(
&format_args!(
modifiers.format(),
space_token(),
name.format(),
property_annotation.format(),
),
semicolon_token.as_ref()
)]
[FormatWithSemicolon::new(&body, semicolon_token.as_ref())]
)
}
}
99 changes: 88 additions & 11 deletions crates/rome_js_formatter/src/utils/assignment_like.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ use crate::utils::object::write_member_name;
use crate::utils::JsAnyBinaryLikeExpression;
use rome_formatter::{format_args, write, VecBuffer};
use rome_js_syntax::{
JsAnyAssignmentPattern, JsAnyBindingPattern, JsAnyExpression, JsAnyFunctionBody,
JsAnyObjectAssignmentPatternMember, JsAnyObjectBindingPatternMember, JsAnyObjectMemberName,
JsAssignmentExpression, JsInitializerClause, JsObjectAssignmentPattern,
JsObjectAssignmentPatternProperty, JsObjectBindingPattern, JsPropertyObjectMember,
JsSyntaxKind, JsVariableDeclarator, TsAnyVariableAnnotation, TsIdentifierBinding, TsType,
JsAnyAssignmentPattern, JsAnyBindingPattern, JsAnyClassMemberName, JsAnyExpression,
JsAnyFunctionBody, JsAnyObjectAssignmentPatternMember, JsAnyObjectBindingPatternMember,
JsAnyObjectMemberName, JsAssignmentExpression, JsInitializerClause, JsLiteralMemberName,
JsObjectAssignmentPattern, JsObjectAssignmentPatternProperty, JsObjectBindingPattern,
JsPropertyClassMember, JsPropertyClassMemberFields, JsPropertyObjectMember, JsSyntaxKind,
JsVariableDeclarator, TsAnyVariableAnnotation, TsIdentifierBinding,
TsPropertySignatureClassMember, TsPropertySignatureClassMemberFields, TsType,
TsTypeAliasDeclaration,
};
use rome_js_syntax::{JsAnyLiteralExpression, JsSyntaxNode};
Expand All @@ -19,11 +21,19 @@ declare_node_union! {
JsAssignmentExpression |
JsObjectAssignmentPatternProperty |
JsVariableDeclarator |
TsTypeAliasDeclaration
TsTypeAliasDeclaration |
JsPropertyClassMember |
TsPropertySignatureClassMember
}

declare_node_union! {
pub(crate) LeftAssignmentLike = JsAnyAssignmentPattern | JsAnyObjectMemberName | JsAnyBindingPattern | TsIdentifierBinding
pub(crate) LeftAssignmentLike =
JsAnyAssignmentPattern |
JsAnyObjectMemberName |
JsAnyBindingPattern |
TsIdentifierBinding |
JsLiteralMemberName |
JsAnyClassMemberName
}

declare_node_union! {
Expand Down Expand Up @@ -297,12 +307,19 @@ impl JsAnyAssignmentLike {
Ok(assignment_pattern.pattern()?.into())
}
JsAnyAssignmentLike::JsVariableDeclarator(variable_declarator) => {
// SAFETY: Calling `unwrap` here is safe because we check `should_only_left` variant at the beginning of the `layout` function
// SAFETY: Calling `unwrap` here is safe because we check `has_only_left_hand_side` variant at the beginning of the `layout` function
Ok(variable_declarator.initializer().unwrap().into())
}
JsAnyAssignmentLike::TsTypeAliasDeclaration(type_alias_declaration) => {
Ok(type_alias_declaration.ty()?.into())
}
JsAnyAssignmentLike::JsPropertyClassMember(n) => {
// SAFETY: Calling `unwrap` here is safe because we check `has_only_left_hand_side` variant at the beginning of the `layout` function
Ok(n.value().unwrap().into())
}
JsAnyAssignmentLike::TsPropertySignatureClassMember(_) => {
unreachable!("TsPropertySignatureClassMember doesn't have any right side. If you're here, `has_only_left_hand_side` hasn't been called")
}
}
}

Expand All @@ -321,6 +338,12 @@ impl JsAnyAssignmentLike {
JsAnyAssignmentLike::TsTypeAliasDeclaration(type_alias_declaration) => {
Ok(type_alias_declaration.binding_identifier()?.into())
}
JsAnyAssignmentLike::JsPropertyClassMember(property_class_member) => {
Ok(property_class_member.name()?.into())
}
JsAnyAssignmentLike::TsPropertySignatureClassMember(
property_signature_class_member,
) => Ok(property_signature_class_member.name()?.into()),
}
}

Expand All @@ -340,7 +363,7 @@ impl JsAnyAssignmentLike {
fn write_left(&self, f: &mut JsFormatter) -> FormatResult<bool> {
match self {
JsAnyAssignmentLike::JsPropertyObjectMember(property) => {
let width = write_member_name(&property.name()?, f)?;
let width = write_member_name(&property.name()?.into(), f)?;
let text_width_for_break =
(u8::from(f.context().tab_width()) + MIN_OVERLAP_FOR_BREAK) as usize;
Ok(width < text_width_for_break)
Expand All @@ -351,7 +374,7 @@ impl JsAnyAssignmentLike {
Ok(false)
}
JsAnyAssignmentLike::JsObjectAssignmentPatternProperty(property) => {
let width = write_member_name(&property.member()?, f)?;
let width = write_member_name(&property.member()?.into(), f)?;
let text_width_for_break =
(u8::from(f.context().tab_width()) + MIN_OVERLAP_FOR_BREAK) as usize;
Ok(width < text_width_for_break)
Expand All @@ -373,6 +396,40 @@ impl JsAnyAssignmentLike {
}
Ok(false)
}
JsAnyAssignmentLike::JsPropertyClassMember(property_class_member) => {
let JsPropertyClassMemberFields {
modifiers,
name,
property_annotation,
value: _,
semicolon_token: _,
} = property_class_member.as_fields();
write!(f, [modifiers.format(), space_token()])?;
let width = write_member_name(&name?.into(), f)?;
write!(f, [property_annotation.format()])?;
let text_width_for_break =
(u8::from(f.context().tab_width()) + MIN_OVERLAP_FOR_BREAK) as usize;
Ok(width < text_width_for_break)
}
JsAnyAssignmentLike::TsPropertySignatureClassMember(
property_signature_class_member,
) => {
let TsPropertySignatureClassMemberFields {
modifiers,
name,
property_annotation,
semicolon_token: _,
} = property_signature_class_member.as_fields();

write!(f, [modifiers.format(), space_token(),])?;

let width = write_member_name(&name?.into(), f)?;

write!(f, [property_annotation.format()])?;
let text_width_for_break =
(u8::from(f.context().tab_width()) + MIN_OVERLAP_FOR_BREAK) as usize;
Ok(width < text_width_for_break)
}
}
}

Expand Down Expand Up @@ -401,6 +458,15 @@ impl JsAnyAssignmentLike {
let eq_token = type_alias_declaration.eq_token()?;
write!(f, [space_token(), eq_token.format()])
}
JsAnyAssignmentLike::JsPropertyClassMember(property_class_member) => {
if let Some(initializer) = property_class_member.value() {
let eq_token = initializer.eq_token()?;
write!(f, [space_token(), eq_token.format()])?
}
Ok(())
}
// this variant doesn't have any operator
JsAnyAssignmentLike::TsPropertySignatureClassMember(_) => Ok(()),
}
}

Expand Down Expand Up @@ -434,6 +500,15 @@ impl JsAnyAssignmentLike {
let ty = type_alias_declaration.ty()?;
write!(f, [space_token(), ty.format()])
}
JsAnyAssignmentLike::JsPropertyClassMember(property_class_member) => {
if let Some(initializer) = property_class_member.value() {
let expression = initializer.expression()?;
write!(f, [space_token(), expression.format()])?;
}
Ok(())
}
// this variant doesn't have any right part
JsAnyAssignmentLike::TsPropertySignatureClassMember(_) => Ok(()),
}
}

Expand Down Expand Up @@ -482,8 +557,10 @@ impl JsAnyAssignmentLike {
fn has_only_left_hand_side(&self) -> bool {
if let JsAnyAssignmentLike::JsVariableDeclarator(declarator) = self {
declarator.initializer().is_none()
} else if let JsAnyAssignmentLike::JsPropertyClassMember(class_member) = self {
class_member.value().is_none()
} else {
false
matches!(self, JsAnyAssignmentLike::TsPropertySignatureClassMember(_))
}
}

Expand Down
34 changes: 28 additions & 6 deletions crates/rome_js_formatter/src/utils/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,39 @@ use crate::prelude::*;
use crate::utils::FormatLiteralStringToken;
use crate::utils::StringLiteralParentKind;
use rome_formatter::write;
use rome_js_syntax::JsAnyObjectMemberName;
use rome_js_syntax::JsSyntaxKind::JS_STRING_LITERAL;
use rome_rowan::AstNode;
use rome_js_syntax::{JsAnyClassMemberName, JsAnyObjectMemberName};
use rome_rowan::{declare_node_union, AstNode};
use unicode_width::UnicodeWidthStr;

declare_node_union! {
pub(crate) JsAnyMemberName = JsAnyObjectMemberName | JsAnyClassMemberName
}

impl Format<JsFormatContext> for JsAnyMemberName {
fn fmt(&self, f: &mut Formatter<JsFormatContext>) -> FormatResult<()> {
match self {
JsAnyMemberName::JsAnyObjectMemberName(node) => {
write!(f, [node.format()])
}
JsAnyMemberName::JsAnyClassMemberName(node) => {
write!(f, [node.format()])
}
}
}
}

pub(crate) fn write_member_name(
name: &JsAnyObjectMemberName,
name: &JsAnyMemberName,
f: &mut JsFormatter,
) -> FormatResult<usize> {
match name {
name @ JsAnyObjectMemberName::JsLiteralMemberName(literal) => {
name @ JsAnyMemberName::JsAnyClassMemberName(JsAnyClassMemberName::JsLiteralMemberName(
literal,
))
| name @ JsAnyMemberName::JsAnyObjectMemberName(
JsAnyObjectMemberName::JsLiteralMemberName(literal),
) => {
let value = literal.value()?;

if value.kind() == JS_STRING_LITERAL {
Expand All @@ -23,13 +45,13 @@ pub(crate) fn write_member_name(

Ok(cleaned.width())
} else {
write!(f, [name.format()])?;
write!(f, [name])?;

Ok(value.text_trimmed().width())
}
}
name => {
write!(f, [&name.format()])?;
write!(f, [&name])?;
Ok(name.text().width())
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
source: crates/rome_js_formatter/tests/prettier_tests.rs
assertion_line: 182
expression: class-property.js
---
# Input
Expand All @@ -18,10 +19,10 @@ class X {
```js
class X {
TEMPLATE =
// tab index is needed so we can focus, which is needed for keyboard events
'<div class="ag-large-text" tabindex="0">' +
'<div class="ag-large-textarea"></div>' +
"</div>";
// tab index is needed so we can focus, which is needed for keyboard events
'<div class="ag-large-text" tabindex="0">' +
'<div class="ag-large-textarea"></div>' +
"</div>";
}

```
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
source: crates/rome_js_formatter/tests/prettier_tests.rs
assertion_line: 182
expression: with_comments.js
---
# Input
Expand All @@ -18,10 +19,10 @@ class A {
```js
class A {
#foobar =
// comment to break
1 +
// comment to break again
2;
// comment to break
1 +
// comment to break again
2;
}

```
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
source: crates/rome_js_formatter/tests/prettier_tests.rs
assertion_line: 182
expression: property.js
---
# Input
Expand Down Expand Up @@ -29,15 +30,15 @@ class B {
```js
class A {
foobar =
// comment to break
1 +
// comment to break again
2;
// comment to break
1 +
// comment to break again
2;
}

class B {
someInstanceProperty = this.props.foofoofoofoofoofoo && this.props
.barbarbarbar;
someInstanceProperty =
this.props.foofoofoofoofoofoo && this.props.barbarbarbar;

someInstanceProperty2 = {
foo: this.props.foofoofoofoofoofoo && this.props.barbarbarbar,
Expand Down
Loading