Skip to content

Commit

Permalink
Added support for spread operator …
Browse files Browse the repository at this point in the history
Fixes #1023
  • Loading branch information
bitwiseman committed Dec 22, 2016
1 parent 3198cea commit e6e3c0a
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 15 deletions.
23 changes: 16 additions & 7 deletions js/lib/beautify.js
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,7 @@ if (!Object.values) {
var second_token = get_token(2);
if (second_token && (
(in_array(second_token.text, [':', ',']) && in_array(next_token.type, ['TK_STRING', 'TK_WORD', 'TK_RESERVED'])) ||
(in_array(next_token.text, ['get', 'set']) && in_array(second_token.type, ['TK_WORD', 'TK_RESERVED']))
(in_array(next_token.text, ['get', 'set', '...']) && in_array(second_token.type, ['TK_WORD', 'TK_RESERVED']))
)) {
// We don't support TypeScript,but we didn't break it for a very long time.
// We'll try to keep not breaking it.
Expand Down Expand Up @@ -1388,7 +1388,15 @@ if (!Object.values) {
}
}

if (in_array(current_token.text, ['--', '++', '!', '~']) || isUnary) {
if (isGeneratorAsterisk) {
allow_wrap_or_preserved_newline();
space_before = false;
space_after = false;
} else if (current_token.text === '...') {
allow_wrap_or_preserved_newline();
space_before = last_type === 'TK_START_BLOCK';
space_after = false;
} else if (in_array(current_token.text, ['--', '++', '!', '~']) || isUnary) {
// unary operators (and binary +/- pretending to be unary) special cases

space_before = false;
Expand Down Expand Up @@ -1430,11 +1438,8 @@ if (!Object.values) {
// foo(); --bar;
print_newline();
}
} else if (isGeneratorAsterisk) {
allow_wrap_or_preserved_newline();
space_before = false;
space_after = false;
}

output.space_before_token = output.space_before_token || space_before;
print_token();
output.space_before_token = space_after;
Expand Down Expand Up @@ -1845,7 +1850,7 @@ if (!Object.values) {
this.positionable_operators = '!= !== % & && * ** + - / : < << <= == === > >= >> >>> ? ^ | ||'.split(' ');
var punct = this.positionable_operators.concat(
// non-positionable operators - these do not follow operator position settings
'! %= &= *= **= ++ += , -- -= /= :: <<= = => >>= >>>= ^= |= ~'.split(' '));
'! %= &= *= **= ++ += , -- -= /= :: <<= = => >>= >>>= ^= |= ~ ...'.split(' '));

// words which should always start on new line.
this.line_starters = 'continue,try,throw,return,var,let,const,if,switch,case,default,for,while,break,function,import,export'.split(',');
Expand Down Expand Up @@ -2312,6 +2317,10 @@ if (!Object.values) {
}

if (c === '.') {
if (input.peek() === '.' && input.peek(1) === '.') {
c += input.next() + input.next();
return [c, 'TK_OPERATOR'];
}
return [c, 'TK_DOT'];
}

Expand Down
11 changes: 11 additions & 0 deletions js/test/generated/beautify-javascript-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,17 @@ function run_javascript_tests(test_obj, Urlencoded, js_beautify, html_beautify,
bt('x ** -2');


//============================================================
// Spread operator
reset_options();
opts.brace_style = "collapse,preserve-inline";
bt('const m = { ...item, c: 3 };');
bt('const m = {\n ...item,\n c: 3\n};');
bt('const m = { c: 3, ...item };');
bt('const m = [...item, 3];');
bt('const m = [3, ...item];');


//============================================================
// Object literal shorthand functions
reset_options();
Expand Down
23 changes: 15 additions & 8 deletions python/jsbeautifier/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,7 @@ def handle_start_block(self, current_token):
second_token = self.get_token(2)
if second_token != None and \
((second_token.text in [':', ','] and next_token.type in ['TK_STRING', 'TK_WORD', 'TK_RESERVED']) \
or (next_token.text in ['get', 'set'] and second_token.type in ['TK_WORD', 'TK_RESERVED'])):
or (next_token.text in ['get', 'set', '...'] and second_token.type in ['TK_WORD', 'TK_RESERVED'])):
# We don't support TypeScript,but we didn't break it for a very long time.
# We'll try to keep not breaking it.
if not self.last_last_text in ['class','interface']:
Expand Down Expand Up @@ -1300,7 +1300,15 @@ def handle_operator(self, current_token):
self.output.space_before_token = True
return

if current_token.text in ['--', '++', '!', '~'] or isUnary:
if isGeneratorAsterisk:
self.allow_wrap_or_preserved_newline(current_token)
space_before = False
space_after = False
elif current_token.text == '...':
self.allow_wrap_or_preserved_newline(current_token)
space_before = self.last_type == 'TK_START_BLOCK'
space_after = False
elif current_token.text in ['--', '++', '!', '~'] or isUnary:
space_before = False
space_after = False

Expand Down Expand Up @@ -1335,11 +1343,6 @@ def handle_operator(self, current_token):
# foo(): --bar
self.print_newline()

elif isGeneratorAsterisk:
self.allow_wrap_or_preserved_newline(current_token)
space_before = False
space_after = False

if space_before:
self.output.space_before_token = True

Expand Down Expand Up @@ -1683,7 +1686,7 @@ class Tokenizer:
positionable_operators = '!= !== % & && * ** + - / : < << <= == === > >= >> >>> ? ^ | ||'.split(' ')
punct = (positionable_operators +
# non-positionable operators - these do not follow operator position settings
'! %= &= *= **= ++ += , -- -= /= :: <<= = => >>= >>>= ^= |= ~'.split(' '))
'! %= &= *= **= ++ += , -- -= /= :: <<= = => >>= >>>= ^= |= ~ ...'.split(' '))

# Words which always should start on a new line
line_starters = 'continue,try,throw,return,var,let,const,if,switch,case,default,for,while,break,function,import,export'.split(',')
Expand Down Expand Up @@ -2084,6 +2087,10 @@ def parse_string(self, resulting_string, delimiter, allow_unescaped_newlines = F
return '-->', 'TK_COMMENT'

if c == '.':
if self.input.peek() == '.' and self.input.peek(1) == '.':
c += self.input.next() + self.input.next()
return c, 'TK_OPERATOR'

return c, 'TK_DOT'

if c in self.punct:
Expand Down
11 changes: 11 additions & 0 deletions python/jsbeautifier/tests/generated/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,17 @@ def unicode_char(value):
bt('x ** -2')


#============================================================
# Spread operator
self.reset_options();
self.options.brace_style = "collapse,preserve-inline"
bt('const m = { ...item, c: 3 };')
bt('const m = {\n ...item,\n c: 3\n};')
bt('const m = { c: 3, ...item };')
bt('const m = [...item, 3];')
bt('const m = [3, ...item];')


#============================================================
# Object literal shorthand functions
self.reset_options();
Expand Down
13 changes: 13 additions & 0 deletions test/data/javascript/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,19 @@ exports.test_data = {
{ unchanged: 'x ** 2' },
{ unchanged: 'x ** -2' }
]
}, {
name: "Spread operator",
description: "Spread operator",
options: [
{ name: 'brace_style', value: '"collapse,preserve-inline"' }
],
tests: [
{ unchanged: 'const m = { ...item, c: 3 };' },
{ unchanged: 'const m = {\n ...item,\n c: 3\n};' },
{ unchanged: 'const m = { c: 3, ...item };' },
{ unchanged: 'const m = [...item, 3];' },
{ unchanged: 'const m = [3, ...item];' }
]
}, {
name: "Object literal shorthand functions",
description: "Object literal shorthand functions",
Expand Down

0 comments on commit e6e3c0a

Please sign in to comment.