Skip to content

Commit

Permalink
feat: add parenExpression.spaceAround (#607)
Browse files Browse the repository at this point in the history
  • Loading branch information
Thristhart authored Feb 8, 2024
1 parent 3bb079a commit 90a5d64
Show file tree
Hide file tree
Showing 6 changed files with 229 additions and 4 deletions.
3 changes: 3 additions & 0 deletions deployment/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,9 @@
"parameters.spaceAround": {
"$ref": "#/definitions/spaceAround"
},
"parenExpression.spaceAround": {
"$ref": "#/definitions/spaceAround"
},
"switchStatement.spaceAround": {
"$ref": "#/definitions/spaceAround"
},
Expand Down
7 changes: 6 additions & 1 deletion src/configuration/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,10 @@ impl ConfigurationBuilder {
self.insert("parameters.spaceAround", value.into())
}

pub fn paren_expression_space_around(&mut self, value: bool) -> &mut Self {
self.insert("parenExpression.spaceAround", value.into())
}

pub fn switch_statement_space_around(&mut self, value: bool) -> &mut Self {
self.insert("switchStatement.spaceAround", value.into())
}
Expand Down Expand Up @@ -1254,12 +1258,13 @@ mod tests {
.for_statement_space_around(true)
.if_statement_space_around(true)
.parameters_space_around(true)
.paren_expression_space_around(true)
.switch_statement_space_around(true)
.tuple_type_space_around(true)
.while_statement_space_around(true);

let inner_config = config.get_inner_config();
assert_eq!(inner_config.len(), 177);
assert_eq!(inner_config.len(), 178);
let diagnostics = resolve_config(inner_config, &Default::default()).diagnostics;
assert_eq!(diagnostics.len(), 0);
}
Expand Down
1 change: 1 addition & 0 deletions src/configuration/resolve_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ pub fn resolve_config(config: ConfigKeyMap, global_config: &GlobalConfiguration)
for_statement_space_around: get_value(&mut config, "forStatement.spaceAround", space_around, &mut diagnostics),
if_statement_space_around: get_value(&mut config, "ifStatement.spaceAround", space_around, &mut diagnostics),
parameters_space_around: get_value(&mut config, "parameters.spaceAround", space_around, &mut diagnostics),
paren_expression_space_around: get_value(&mut config, "parenExpression.spaceAround", space_around, &mut diagnostics),
switch_statement_space_around: get_value(&mut config, "switchStatement.spaceAround", space_around, &mut diagnostics),
tuple_type_space_around: get_value(&mut config, "tupleType.spaceAround", space_around, &mut diagnostics),
while_statement_space_around: get_value(&mut config, "whileStatement.spaceAround", space_around, &mut diagnostics),
Expand Down
2 changes: 2 additions & 0 deletions src/configuration/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,8 @@ pub struct Configuration {
pub if_statement_space_around: bool,
#[serde(rename = "parameters.spaceAround")]
pub parameters_space_around: bool,
#[serde(rename = "parenExpression.spaceAround")]
pub paren_expression_space_around: bool,
#[serde(rename = "switchStatement.spaceAround")]
pub switch_statement_space_around: bool,
#[serde(rename = "tupleType.spaceAround")]
Expand Down
22 changes: 19 additions & 3 deletions src/generation/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2572,7 +2572,11 @@ fn gen_fn_expr<'a>(node: &FnExpr<'a>, context: &mut Context<'a>) -> PrintItems {
);

if should_add_parens_around_expr(node.into(), context) {
surround_with_parens(items)
if context.config.paren_expression_space_around {
surround_with_parens(surround_with_spaces(items))
} else {
surround_with_parens(items)
}
} else {
items
}
Expand Down Expand Up @@ -2741,7 +2745,11 @@ fn gen_object_lit<'a>(node: &ObjectLit<'a>, context: &mut Context<'a>) -> PrintI
);

if should_add_parens_around_expr(node.into(), context) {
surround_with_parens(items)
surround_with_parens(if context.config.paren_expression_space_around {
surround_with_spaces(items)
} else {
items
})
} else {
items
}
Expand All @@ -2758,7 +2766,7 @@ fn gen_paren_expr<'a>(node: &'a ParenExpr<'a>, context: &mut Context<'a>) -> Pri
inner_range: node.expr.range(),
prefer_hanging: true,
allow_open_paren_trailing_comments: true,
single_line_space_around: false,
single_line_space_around: context.config.paren_expression_space_around,
},
context,
))
Expand Down Expand Up @@ -9380,6 +9388,14 @@ fn surround_with_parens(items: PrintItems) -> PrintItems {
new_items
}

fn surround_with_spaces(items: PrintItems) -> PrintItems {
let mut new_items = PrintItems::new();
new_items.push_str(" ");
new_items.extend(items);
new_items.push_str(" ");
new_items
}

/* is/has functions */

fn is_arrow_function_with_expr_body(node: Node) -> bool {
Expand Down
198 changes: 198 additions & 0 deletions tests/specs/expressions/ParenExpr/ParenExpr_SpaceAround_True.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
~~ parenExpression.spaceAround: true ~~
== should format allowing comment on header line ==
const test = ( // test
test
);

[expect]
const test = ( // test
test
);

== should keep comment inside ==
const test = (
// test
test
);

[expect]
const test = (
// test
test
);

== should keep paren expr on left hand side of assignment ==
(x.test as unknown) = 6;

[expect]
( x.test as unknown ) = 6;

== should not keep paren expr on right hand side of assignment ==
const a = (1);
const b = ((((1))));
const c = (1 + 1) + 1;
const d = 1 + (1 + 1);
// except here it should because of the type assertion
const e = /** @type {number} */ (((1)));
// keep this too as some people like it for clarity
const a = (b = 5);

[expect]
const a = 1;
const b = 1;
const c = ( 1 + 1 ) + 1;
const d = 1 + ( 1 + 1 );
// except here it should because of the type assertion
const e = /** @type {number} */ ( 1 );
// keep this too as some people like it for clarity
const a = ( b = 5 );

== should keep for IIFE ==
(function foo() {
test;
})();

(() => {
test;
})();

((() => {
test;
}))();

(function foo() {
test;
})((function test() {}));

[expect]
( function foo() {
test;
} )();

( () => {
test;
} )();

( () => {
test;
} )();

( function foo() {
test;
} )(function test() {});

== should keep for property access expr where appropriate ==
(function test() {
test;
}).prop;

(() => {
test;
}).prop;

({
prop: 5,
}).prop;

([5]).prop;

[expect]
( function test() {
test;
} ).prop;

( () => {
test;
} ).prop;

( {
prop: 5,
} ).prop;

[5].prop;

== should handle wrapped exprs for function expressions ==
(function test() {}());
(function test() {}?.());
(function test() {}.prop);
(function test() {}?.prop);
(function test() {}[56]);
(function test() {} + 2);
(2 + function test() {});
1 + (function test() {} + 2);
obj[(function test() {})];
(function test() {}) ? true : false;
true ? function test() {} : false;
true ? true : function test() {};

[expect]
( function test() {} )();
( function test() {} )?.();
( function test() {} ).prop;
( function test() {} )?.prop;
( function test() {} )[56];
( function test() {} ) + 2;
2 + function test() {};
1 + ( function test() {} + 2 );
obj[function test() {}];
( function test() {} ) ? true : false;
true ? function test() {} : false;
true ? true : function test() {};

== should handle wrapped exprs for arrow fn expressions ==
(() => {})();
(() => {})?.();
(() => {}).prop;
(() => {})?.prop;
(() => {})[56];
(() => {}) + 2;
1 + ((() => {}) + 2);
obj[() => {}];
(() => {}) ? true : false;
true ? () => {} : false;
true ? true : () => {};
new (() => {})();
test = (() => {});
test = () => {};

[expect]
( () => {} )();
( () => {} )?.();
( () => {} ).prop;
( () => {} )?.prop;
( () => {} )[56];
( () => {} ) + 2;
1 + ( ( () => {} ) + 2 );
obj[() => {}];
( () => {} ) ? true : false;
true ? () => {} : false;
true ? true : () => {};
new ( () => {} )();
test = () => {};
test = () => {};

== should handle object literal expr in paren expr in expr stmt ==
({ prop: 5 }.prop);
({ prop: 5 }).prop;

[expect]
( { prop: 5 } ).prop;
( { prop: 5 } ).prop;

== should not remove when there's a JS doc type assertion ==
typeAssertedNumber = /** @type {number} */ (numberOrString)
// not a js doc so won't keep it
typeAssertedNumber = /* @type {number} */ (numberOrString);

[expect]
typeAssertedNumber = /** @type {number} */ ( numberOrString );
// not a js doc so won't keep it
typeAssertedNumber = /* @type {number} */ numberOrString;

== should add spaces for update expr with assertion ==
(<number>thing)--;
(thing as number)--;

[expect]
( <number> thing )--;
( thing as number )--;

0 comments on commit 90a5d64

Please sign in to comment.