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

feat(rome_js_formatter): Object Pattern Formatting #3405

Merged
merged 4 commits into from
Oct 12, 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
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ use rome_js_syntax::{
JsLanguage, JsSyntaxKind, JsxAnyChild, JsxAnyElementName, JsxAnyTag, JsxChildList, JsxElement,
JsxFragment, JsxTagExpression,
};
use rome_rowan::{declare_node_union, AstNode, AstNodeList, BatchMutation, BatchMutationExt};
use rome_rowan::{
declare_node_union, AstNode, AstNodeList, BatchMutation, BatchMutationExt, SyntaxNodeOptionExt,
};

declare_rule! {
/// Disallow unnecessary fragments
Expand Down Expand Up @@ -111,7 +113,7 @@ impl Rule for NoUselessFragments {
.parent()
.map(|parent| match JsxTagExpression::try_cast(parent) {
Ok(parent) => {
let parent_kind = parent.syntax().parent().map(|p| p.kind());
let parent_kind = parent.syntax().parent().kind();
matches!(
parent_kind,
Some(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use rome_js_syntax::{
JsPrivateClassMemberName, JsPropertyClassMember, JsSetterClassMember, JsSyntaxKind,
JsVariableDeclaration, JsVariableDeclarator, JsVariableDeclaratorList, JsxReferenceIdentifier,
};
use rome_rowan::{declare_node_union, AstNode, BatchMutationExt};
use rome_rowan::{declare_node_union, AstNode, BatchMutationExt, SyntaxNodeOptionExt};
use std::{borrow::Cow, iter::once};

declare_rule! {
Expand Down Expand Up @@ -67,7 +67,7 @@ fn is_non_camel_ok(binding: &JsIdentifierBinding, model: &SemanticModel) -> Opti
match binding.syntax().parent()?.kind() {
JS_VARIABLE_DECLARATOR => {
let declarator = binding.parent::<JsVariableDeclarator>()?;
let is_ok = match declarator.syntax().parent().map(|parent| parent.kind()) {
let is_ok = match declarator.syntax().parent().kind() {
Some(JS_VARIABLE_DECLARATOR_LIST) => declarator
.parent::<JsVariableDeclaratorList>()?
.parent::<JsVariableDeclaration>()?
Expand Down
4 changes: 2 additions & 2 deletions crates/rome_js_formatter/src/comments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rome_js_syntax::{
JsFormalParameter, JsFunctionBody, JsIdentifierExpression, JsIfStatement, JsLanguage,
JsSyntaxKind, JsSyntaxNode, JsVariableDeclarator, JsWhileStatement, TsInterfaceDeclaration,
};
use rome_rowan::{AstNode, SyntaxTriviaPieceComments, TextLen};
use rome_rowan::{AstNode, SyntaxNodeOptionExt, SyntaxTriviaPieceComments, TextLen};

pub type JsComments = Comments<JsLanguage>;

Expand Down Expand Up @@ -965,7 +965,7 @@ fn handle_variable_declarator_comment(
}
}
JsSyntaxKind::JS_INITIALIZER_CLAUSE => {
let parent_kind = enclosing.parent().map(|p| p.kind());
let parent_kind = enclosing.parent().kind();

if matches!(
parent_kind,
Expand Down
2 changes: 1 addition & 1 deletion crates/rome_js_formatter/src/js/bindings/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ pub enum ParameterLayout {
Default,
}

fn should_hug_function_parameters(
pub(crate) fn should_hug_function_parameters(
parameters: &FormatJsAnyParameters,
comments: &JsComments,
) -> FormatResult<bool> {
Expand Down
4 changes: 2 additions & 2 deletions crates/rome_js_formatter/src/js/statements/block_statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rome_js_syntax::{JsAnyStatement, JsEmptyStatement};

use rome_js_syntax::JsBlockStatementFields;
use rome_js_syntax::JsSyntaxKind;
use rome_rowan::{AstNode, AstNodeList};
use rome_rowan::{AstNode, AstNodeList, SyntaxNodeOptionExt};

#[derive(Debug, Clone, Default)]
pub struct FormatJsBlockStatement;
Expand Down Expand Up @@ -96,7 +96,7 @@ fn is_empty_block(block: &JsBlockStatement, comments: &JsComments) -> bool {
fn is_non_collapsible(block: &JsBlockStatement) -> bool {
// reference https://github.com/prettier/prettier/blob/b188c905cfaeb238a122b4a95c230da83f2f3226/src/language-js/print/block.js#L19
let parent = block.syntax().parent();
match parent.clone().map(|p| p.kind()) {
match parent.kind() {
Some(
JsSyntaxKind::JS_FUNCTION_BODY
| JsSyntaxKind::JS_FOR_STATEMENT
Expand Down
4 changes: 2 additions & 2 deletions crates/rome_js_formatter/src/js/statements/empty_statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ use crate::prelude::*;
use rome_formatter::write;

use rome_js_syntax::{JsEmptyStatement, JsEmptyStatementFields, JsSyntaxKind};
use rome_rowan::AstNode;
use rome_rowan::{AstNode, SyntaxNodeOptionExt};

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

impl FormatNodeRule<JsEmptyStatement> for FormatJsEmptyStatement {
fn fmt_fields(&self, node: &JsEmptyStatement, f: &mut JsFormatter) -> FormatResult<()> {
let JsEmptyStatementFields { semicolon_token } = node.as_fields();
let parent_kind = node.syntax().parent().map(|p| p.kind());
let parent_kind = node.syntax().parent().kind();

if matches!(
parent_kind,
Expand Down
3 changes: 2 additions & 1 deletion crates/rome_js_formatter/src/ts/types/union_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::utils::{
use rome_formatter::{format_args, write, Buffer};
use rome_js_syntax::{JsSyntaxKind, JsSyntaxToken, TsTupleTypeElementList, TsUnionType};
use rome_js_syntax::{JsSyntaxNode, TsUnionTypeFields};
use rome_rowan::SyntaxNodeOptionExt;

#[derive(Debug, Clone, Default)]
pub struct FormatTsUnionType;
Expand Down Expand Up @@ -39,7 +40,7 @@ impl FormatNodeRule<TsUnionType> for FormatTsUnionType {
let has_leading_comments = f.comments().has_leading_comments(node.syntax());

let should_indent = {
let parent_kind = node.syntax().parent().map(|p| p.kind());
let parent_kind = node.syntax().parent().kind();

// These parents have indent for their content, so we don't need to indent here
!match parent_kind {
Expand Down
110 changes: 59 additions & 51 deletions crates/rome_js_formatter/src/utils/assignment_like.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use rome_js_syntax::{
TsAnyVariableAnnotation, TsIdentifierBinding, TsPropertySignatureClassMember,
TsPropertySignatureClassMemberFields, TsType, TsTypeAliasDeclaration, TsTypeArguments,
};
use rome_rowan::{declare_node_union, AstNode, SyntaxResult};
use rome_rowan::{declare_node_union, AstNode, SyntaxNodeOptionExt, SyntaxResult};
use std::iter;

declare_node_union! {
Expand Down Expand Up @@ -50,69 +50,78 @@ declare_node_union! {
}

impl AnyObjectPattern {
fn is_complex(&self) -> SyntaxResult<bool> {
/// Determines if this is a complex pattern. A pattern is considered complex if it has more than 2 properties
/// and any property:
///
/// * is a shorthand property with an initializer
/// * is a non-shorthand property
///
/// ## Examples
///
/// ```javascript
/// let { a, b, c = "test"} = ...
/// ```
///
/// Is considered a complex binding because it has three properties and a shorthand property with an initializer.
///
/// ```javascript
/// let { a, b, c: d } = ...
/// ```
///
/// Is considered a complex binding because it has three properties and a non-shorthand property
///
fn is_complex(&self) -> bool {
match self {
AnyObjectPattern::JsObjectAssignmentPattern(assignment_pattern) => {
let properties_len = assignment_pattern.properties().len();
if properties_len <= 2 {
return Ok(false);
use JsAnyObjectAssignmentPatternMember::*;

if assignment_pattern.properties().len() <= 2 {
return false;
}
// A binding is complex when we have at least one [JsObjectBindingPatternProperty]
// e.g. a = { a: c = f } = a
// The `c = f` will trigger the complex binding
let has_at_least_a_complex_binding = assignment_pattern

assignment_pattern
.properties()
.iter()
.map(|p| p.ok())
.any(|property| {
let property = property;

matches!(
property,
Some(
JsAnyObjectAssignmentPatternMember::JsObjectAssignmentPatternProperty(_),
)
)
});
Ok(has_at_least_a_complex_binding)
.flatten()
.any(|property| match property {
JsObjectAssignmentPatternProperty(_) => true,
JsObjectAssignmentPatternShorthandProperty(short) => short.init().is_some(),
_ => false,
})
}
AnyObjectPattern::JsObjectBindingPattern(binding_pattern) => {
let properties_len = binding_pattern.properties().len();
if properties_len <= 2 {
return Ok(false);
use JsAnyObjectBindingPatternMember::*;

if binding_pattern.properties().len() <= 2 {
return false;
}
// A binding is complex when we have at least one [JsObjectBindingPatternProperty]
// e.g. const a = { a: c = f } = a
// The `c = f` will trigger the complex binding
let has_at_least_a_complex_binding = binding_pattern

binding_pattern
.properties()
.iter()
.map(|p| p.ok())
.any(|property| {
let property = property;

matches!(
property,
Some(
JsAnyObjectBindingPatternMember::JsObjectBindingPatternProperty(_),
)
)
});
Ok(has_at_least_a_complex_binding)
.flatten()
.any(|property| match property {
JsObjectBindingPatternProperty(_) => true,
JsObjectBindingPatternShorthandProperty(member) => member.init().is_some(),
_ => false,
})
}
}
}
}

impl LeftAssignmentLike {
fn as_object_pattern(&self) -> Option<AnyObjectPattern> {
fn into_object_pattern(self) -> Option<AnyObjectPattern> {
use JsAnyAssignmentPattern::*;
use JsAnyBindingPattern::*;

match self {
LeftAssignmentLike::JsAnyAssignmentPattern(
JsAnyAssignmentPattern::JsObjectAssignmentPattern(node),
) => Some(AnyObjectPattern::from(node.clone())),
LeftAssignmentLike::JsAnyBindingPattern(
JsAnyBindingPattern::JsObjectBindingPattern(node),
) => Some(AnyObjectPattern::from(node.clone())),
LeftAssignmentLike::JsAnyAssignmentPattern(JsObjectAssignmentPattern(node)) => {
Some(AnyObjectPattern::from(node))
}
LeftAssignmentLike::JsAnyBindingPattern(JsObjectBindingPattern(node)) => {
Some(AnyObjectPattern::from(node))
}
_ => None,
}
}
Expand Down Expand Up @@ -721,7 +730,7 @@ impl JsAnyAssignmentLike {
JsSyntaxKind::JS_ASSIGNMENT_EXPRESSION
| JsSyntaxKind::JS_INITIALIZER_CLAUSE
) {
let great_parent_kind = parent.parent().map(|n| n.kind());
let great_parent_kind = parent.parent().kind();
// Finally, we check the great parent.
// The great parent triggers the eligibility when
// - the current node that we were inspecting is not a "tail"
Expand Down Expand Up @@ -808,9 +817,8 @@ impl JsAnyAssignmentLike {
fn should_break_left_hand_side(&self) -> SyntaxResult<bool> {
let is_complex_destructuring = self
.left()?
.as_object_pattern()
.and_then(|pattern| pattern.is_complex().ok())
.unwrap_or(false);
.into_object_pattern()
.map_or(false, |pattern| pattern.is_complex());

let has_complex_type_annotation = self
.annotation()
Expand Down
Loading
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载