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

Commit

Permalink
chore: add group to left-hand side conditionally
Browse files Browse the repository at this point in the history
  • Loading branch information
ematipico committed Jun 22, 2022
1 parent b168b2e commit 8ef485a
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 17 deletions.
5 changes: 5 additions & 0 deletions crates/rome_formatter/src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ impl<'a, Context> VecBuffer<'a, Context> {
FormatElement::List(List::new(std::mem::take(&mut self.elements)))
}
}

/// Returns a reference to the current context
pub fn context(&self) -> &Context {
&self.state.context
}
}

impl<Context> Deref for VecBuffer<'_, Context> {
Expand Down
48 changes: 37 additions & 11 deletions crates/rome_js_formatter/src/utils/assignment_like.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::prelude::*;
use crate::utils::object::write_member_name;
use crate::utils::JsAnyBinaryLikeExpression;
use rome_formatter::{format_args, write};
use rome_formatter::{format_args, write, VecBuffer};
use rome_js_syntax::{
JsAnyAssignmentPattern, JsAnyExpression, JsAnyFunctionBody, JsAnyObjectAssignmentPatternMember,
JsAnyObjectBindingPatternMember, JsAnyObjectMemberName, JsAssignmentExpression,
Expand Down Expand Up @@ -115,7 +115,7 @@ impl Format<JsFormatContext> for RightAssignmentLike {
/// Assignment like are:
/// - Assignment
/// - Object property member
#[derive(Debug)]
#[derive(Debug, Eq, PartialEq)]
pub(crate) enum AssignmentLikeLayout {
/// First break right-hand side, then after operator.
/// ```js
Expand Down Expand Up @@ -235,23 +235,23 @@ impl JsAnyAssignmentLike {
const MIN_OVERLAP_FOR_BREAK: u8 = 3;

impl JsAnyAssignmentLike {
fn write_left(&self, f: &mut JsFormatter) -> FormatResult<bool> {
fn write_left(&self, buffer: &mut VecBuffer<JsFormatContext>) -> FormatResult<bool> {
match self {
JsAnyAssignmentLike::JsPropertyObjectMember(property) => {
let width = write_member_name(&property.name()?, f)?;
let width = write_member_name(&property.name()?, buffer)?;
let text_width_for_break =
(f.context().tab_width() + MIN_OVERLAP_FOR_BREAK) as usize;
(buffer.context().tab_width() + MIN_OVERLAP_FOR_BREAK) as usize;
Ok(width < text_width_for_break)
}
JsAnyAssignmentLike::JsAssignmentExpression(assignment) => {
let left = assignment.left()?;
write!(f, [group_elements(&left.format())])?;
write!(buffer, [&left.format()])?;
Ok(false)
}
JsAnyAssignmentLike::JsObjectAssignmentPatternProperty(property) => {
let width = write_member_name(&property.member()?, f)?;
let width = write_member_name(&property.member()?, buffer)?;
let text_width_for_break =
(f.context().tab_width() + MIN_OVERLAP_FOR_BREAK) as usize;
(buffer.context().tab_width() + MIN_OVERLAP_FOR_BREAK) as usize;
Ok(width < text_width_for_break)
}
}
Expand Down Expand Up @@ -502,14 +502,40 @@ pub(crate) fn has_new_line_before_comment(node: &JsSyntaxNode) -> bool {
impl Format<JsFormatContext> for JsAnyAssignmentLike {
fn fmt(&self, f: &mut JsFormatter) -> FormatResult<()> {
let format_content = format_with(|f| {
// We create a temporary buffer because the left hand side had to conditionally add
// a group based on the layout, but the layout can be computed when the left hand
// side is actually formatted.
//
// 1. we crate a temporary buffer
// 2. we write the left hand side into the buffer and retrieve the `is_left_short` info
// 3. we compute the layout
// 4. we write the left node inside the main buffer based on the layout
let mut buffer = VecBuffer::new(f.state_mut());
let is_left_short = self.write_left(&mut buffer)?;

// Compare name only if we are in a position of computing it.
// If not (for example, left is not an identifier), then let's fallback to false,
// so we can continue the chain of checks
let is_left_short = self.write_left(f)?;
self.write_operator(f)?;

let layout = self.layout(is_left_short)?;

let formatted_element = buffer.into_element();

if layout == AssignmentLikeLayout::BreakLeftHandSide {
write!(
f,
[&format_once(|f| { f.write_element(formatted_element) })]
)?;
} else {
write!(
f,
[group_elements(&format_once(|f| {
f.write_element(formatted_element)
}))]
)?;
}

self.write_operator(f)?;

let right = &format_with(|f| self.write_right(f)).memoized();

let inner_content = format_with(|f| match &layout {
Expand Down
12 changes: 6 additions & 6 deletions crates/rome_js_formatter/src/utils/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,35 @@ use crate::prelude::*;

use crate::utils::FormatLiteralStringToken;
use crate::utils::StringLiteralParentKind;
use rome_formatter::write;
use rome_formatter::{write, VecBuffer};
use rome_js_syntax::JsAnyObjectMemberName;
use rome_js_syntax::JsSyntaxKind::JS_STRING_LITERAL;
use rome_rowan::AstNode;
use unicode_width::UnicodeWidthStr;

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

if value.kind() == JS_STRING_LITERAL {
let format = FormatLiteralStringToken::new(&value, StringLiteralParentKind::Member);
let cleaned = format.clean_text(f.context());
let cleaned = format.clean_text(buffer.context());

cleaned.fmt(f)?;
write!(buffer, [cleaned])?;

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

Ok(value.text_trimmed().width())
}
}
name => {
write!(f, [group_elements(&name.format())])?;
write!(buffer, [&name.format()])?;
Ok(name.text().width())
}
}
Expand Down

0 comments on commit 8ef485a

Please sign in to comment.