Destructuring, importing, and short objects

Fixes #114
Fixes #315
Fixes #370
Fixes #382
This commit is contained in:
Liam Newman 2016-01-22 11:51:06 -08:00
parent 49624f9c41
commit 55f111eecd
7 changed files with 417 additions and 48 deletions

View File

@ -1,5 +1,6 @@
# JS Beautifier
[![Build Status](https://img.shields.io/travis/beautify-web/js-beautify/master.svg)](http://travis-ci.org/beautify-web/js-beautify)
[![Build status](https://ci.appveyor.com/api/projects/status/5bxmpvew5n3e58te/branch/master?svg=true)](https://ci.appveyor.com/project/beautify-web/js-beautify/branch/master)
[![NPM version](https://img.shields.io/npm/v/js-beautify.svg)](https://www.npmjs.com/package/js-beautify)
[![Download stats](https://img.shields.io/npm/dm/js-beautify.svg)](https://www.npmjs.com/package/js-beautify)
[![Join the chat at https://gitter.im/beautify-web/js-beautify](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/beautify-web/js-beautify?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

View File

@ -356,6 +356,7 @@
<select id="brace-style">
<option value="collapse">Braces with control statement</option>
<option value="collapse-preserve-inline">Braces with control statement, preserve inline</option>
<option value="expand">Braces on own line</option>
<option value="end-expand">End braces on own line</option>
<option value="none">Attempt to keep braces where

View File

@ -61,7 +61,7 @@
space_after_anon_function (default false) - should the space before an anonymous function's parens be added, "function()" vs "function ()",
NOTE: This option is overriden by jslint_happy (i.e. if jslint_happy is true, space_after_anon_function is true by design)
brace_style (default "collapse") - "collapse" | "expand" | "end-expand" | "none"
brace_style (default "collapse") - "collapse-preserve-inline" | "collapse" | "expand" | "end-expand" | "none"
put braces on the same line as control statements (default), or put braces on own line (Allman / ANSI style), or just put end braces on own line, or attempt to keep them where they are.
space_before_conditional (default true) - should the space before conditional statement be added, "if(true)" vs "if (true)",
@ -239,6 +239,7 @@
declaration_statement: false,
declaration_assignment: false,
multiline_frame: false,
inline_frame: false,
if_block: false,
else_block: false,
do_block: false,
@ -766,20 +767,22 @@
set_mode(MODE.BlockStatement);
}
} else if (in_array(last_type, ['TK_EQUALS', 'TK_START_EXPR', 'TK_COMMA', 'TK_OPERATOR']) ||
(last_type === 'TK_RESERVED' && in_array(flags.last_text, ['return', 'throw']))
(last_type === 'TK_RESERVED' && in_array(flags.last_text, ['return', 'throw', 'import']))
) {
// Detecting shorthand function syntax is difficult by scanning forward, so check the surrounding context.
// If the block is being returned, passed as arg, assigned with = or assigned in a nested object, treat as an ObjectLiteral.
// Detecting shorthand function syntax is difficult by scanning forward,
// so check the surrounding context.
// If the block is being returned, imported, passed as arg,
// assigned with = or assigned in a nested object, treat as an ObjectLiteral.
set_mode(MODE.ObjectLiteral);
} else {
set_mode(MODE.BlockStatement);
}
var empty_braces = !next_token.comments_before.length && next_token.text === '}';
var empty_anonymous_function = empty_braces && flags.last_word === 'function' &&
last_type === 'TK_END_EXPR';
if (opt.brace_style === "expand" ||
(opt.brace_style === "none" && current_token.wanted_newline)) {
if (last_type !== 'TK_OPERATOR' &&
@ -791,22 +794,39 @@
print_newline(false, true);
}
} else { // collapse
if (last_type !== 'TK_OPERATOR' && last_type !== 'TK_START_EXPR') {
if (opt.brace_style === 'collapse-preserve-inline') {
// search forward for a newline wanted inside this block
var index = 0;
var check_token = null;
flags.inline_frame = true;
do {
index += 1;
check_token = get_token(index);
if (check_token.wanted_newline) {
flags.inline_frame = false;
break;
}
} while (check_token.type !== 'TK_EOF' &&
!(check_token.type === 'TK_END_BLOCK' && check_token.opened === current_token))
}
if (is_array(previous_flags.mode) && (last_type === 'TK_START_EXPR' || last_type === 'TK_COMMA')) {
// if we're preserving inline,
// allow newline between comma and next brace.
if (flags.inline_frame) {
allow_wrap_or_preserved_newline();
flags.inline_frame = true;
previous_flags.multiline_frame = previous_flags.multiline_frame || flags.multiline_frame;
flags.multiline_frame = false;
} else {
output.space_before_token = last_type === 'TK_COMMA';
}
} else if (last_type !== 'TK_OPERATOR' && last_type !== 'TK_START_EXPR') {
if (last_type === 'TK_START_BLOCK') {
print_newline();
} else {
output.space_before_token = true;
}
} else {
// if TK_OPERATOR or TK_START_EXPR
if (is_array(previous_flags.mode) && flags.last_text === ',') {
if (last_last_text === '}') {
// }, { in array context
output.space_before_token = true;
} else {
print_newline(); // [a, b, c, {
}
}
}
}
print_token();
@ -827,7 +847,9 @@
} else {
// skip {}
if (!empty_braces) {
if (is_array(flags.mode) && opt.keep_array_indentation) {
if (flags.inline_frame) {
output.space_before_token = true;
} else if (is_array(flags.mode) && opt.keep_array_indentation) {
// we REALLY need a newline here, but newliner would skip that
opt.keep_array_indentation = false;
print_newline();
@ -951,7 +973,8 @@
prefix = 'NONE';
if (last_type === 'TK_END_BLOCK') {
if (!(current_token.type === 'TK_RESERVED' && in_array(current_token.text, ['else', 'catch', 'finally']))) {
if (!(current_token.type === 'TK_RESERVED' && in_array(current_token.text, ['else', 'catch', 'finally', 'from']))) {
prefix = 'NEWLINE';
} else {
if (opt.brace_style === "expand" ||
@ -974,7 +997,11 @@
(flags.last_text === '*' && last_last_text === 'function')) {
prefix = 'SPACE';
} else if (last_type === 'TK_START_BLOCK') {
prefix = 'NEWLINE';
if (flags.inline_frame) {
prefix = 'SPACE';
} else {
prefix = 'NEWLINE';
}
} else if (last_type === 'TK_END_EXPR') {
output.space_before_token = true;
prefix = 'NEWLINE';
@ -1056,7 +1083,7 @@
// The conditional starts the statement if appropriate.
// One difference - strings want at least a space before
output.space_before_token = true;
} else if (last_type === 'TK_RESERVED' || last_type === 'TK_WORD') {
} else if (last_type === 'TK_RESERVED' || last_type === 'TK_WORD' || flags.inline_frame) {
output.space_before_token = true;
} else if (last_type === 'TK_COMMA' || last_type === 'TK_START_EXPR' || last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {
if (!start_of_object_property()) {
@ -1106,15 +1133,18 @@
}
print_token();
output.space_before_token = true;
if (flags.mode === MODE.ObjectLiteral ||
(flags.mode === MODE.Statement && flags.parent.mode === MODE.ObjectLiteral)) {
if (flags.mode === MODE.Statement) {
restore_mode();
}
print_newline();
if (!flags.inline_frame) {
print_newline();
}
} else {
// EXPR or DO_BLOCK
output.space_before_token = true;
// for comma-first, we want to allow a newline before the comma
// to turn into a newline after the comma, which we will fixup later
if (opt.comma_first) {
@ -1200,7 +1230,9 @@
}
}
if ((flags.mode === MODE.BlockStatement || flags.mode === MODE.Statement) && (flags.last_text === '{' || flags.last_text === ';')) {
if (((flags.mode === MODE.BlockStatement && !flags.inline_frame) || flags.mode === MODE.Statement)
&& (flags.last_text === '{' || flags.last_text === ';')) {
// { foo; --i }
// foo(); --bar;
print_newline();
@ -1556,6 +1588,7 @@
this.wanted_newline = newlines > 0;
this.whitespace_before = whitespace_before || '';
this.parent = null;
this.opened = null;
this.directives = null;
}
@ -1570,7 +1603,7 @@
var punct = ('+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! ~ , : ? ^ ^= |= :: => **').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(',');
var reserved_words = this.line_starters.concat(['do', 'in', 'else', 'get', 'set', 'new', 'catch', 'finally', 'typeof', 'yield', 'async', 'await']);
var reserved_words = this.line_starters.concat(['do', 'in', 'else', 'get', 'set', 'new', 'catch', 'finally', 'typeof', 'yield', 'async', 'await', 'from']);
// /* ... */ comment ends with nearest */ or end of file
var block_comment_pattern = /([\s\S]*?)((?:\*\/)|$)/g;
@ -1627,6 +1660,8 @@
(next.text === ')' && open.text === '(') ||
(next.text === '}' && open.text === '{')))) {
next.parent = open.parent;
next.opened = open
open = open_stack.pop();
}

View File

@ -300,6 +300,35 @@ function run_javascript_tests(test_obj, Urlencoded, js_beautify, html_beautify,
test_fragment('\n', '');
// Brace style permutations - (ibo = "", iao = "", ibc = "", iac = "", obo = " ", oao = " ", obc = " ", oac = " ")
opts.brace_style = 'collapse-preserve-inline';
bt('var a ={a: 2};\nvar a ={a: 2};', 'var a = { a: 2 };\nvar a = { a: 2 };');
bt('//case 1\nif (a == 1){}\n//case 2\nelse if (a == 2){}', '//case 1\nif (a == 1) {}\n//case 2\nelse if (a == 2) {}');
bt('if(1){2}else{3}', 'if (1) { 2 } else { 3 }');
bt('try{a();}catch(b){c();}catch(d){}finally{e();}', 'try { a(); } catch (b) { c(); } catch (d) {} finally { e(); }');
// Brace style permutations - (ibo = "\n", iao = "\n", ibc = "\n", iac = "\n", obo = " ", oao = "\n ", obc = "\n", oac = " ")
opts.brace_style = 'collapse-preserve-inline';
bt('var a =\n{\na: 2\n}\n;\nvar a =\n{\na: 2\n}\n;', 'var a = {\n a: 2\n};\nvar a = {\n a: 2\n};');
bt('//case 1\nif (a == 1)\n{}\n//case 2\nelse if (a == 2)\n{}', '//case 1\nif (a == 1) {}\n//case 2\nelse if (a == 2) {}');
bt('if(1)\n{\n2\n}\nelse\n{\n3\n}', 'if (1) {\n 2\n} else {\n 3\n}');
bt('try\n{\na();\n}\ncatch(b)\n{\nc();\n}\ncatch(d)\n{}\nfinally\n{\ne();\n}', 'try {\n a();\n} catch (b) {\n c();\n} catch (d) {} finally {\n e();\n}');
// Brace style permutations - (ibo = "", iao = "", ibc = "", iac = "", obo = " ", oao = "\n ", obc = "\n", oac = " ")
opts.brace_style = 'collapse';
bt('var a ={a: 2};\nvar a ={a: 2};', 'var a = {\n a: 2\n};\nvar a = {\n a: 2\n};');
bt('//case 1\nif (a == 1){}\n//case 2\nelse if (a == 2){}', '//case 1\nif (a == 1) {}\n//case 2\nelse if (a == 2) {}');
bt('if(1){2}else{3}', 'if (1) {\n 2\n} else {\n 3\n}');
bt('try{a();}catch(b){c();}catch(d){}finally{e();}', 'try {\n a();\n} catch (b) {\n c();\n} catch (d) {} finally {\n e();\n}');
// Brace style permutations - (ibo = "\n", iao = "\n", ibc = "\n", iac = "\n", obo = " ", oao = "\n ", obc = "\n", oac = " ")
opts.brace_style = 'collapse';
bt('var a =\n{\na: 2\n}\n;\nvar a =\n{\na: 2\n}\n;', 'var a = {\n a: 2\n};\nvar a = {\n a: 2\n};');
bt('//case 1\nif (a == 1)\n{}\n//case 2\nelse if (a == 2)\n{}', '//case 1\nif (a == 1) {}\n//case 2\nelse if (a == 2) {}');
bt('if(1)\n{\n2\n}\nelse\n{\n3\n}', 'if (1) {\n 2\n} else {\n 3\n}');
bt('try\n{\na();\n}\ncatch(b)\n{\nc();\n}\ncatch(d)\n{}\nfinally\n{\ne();\n}', 'try {\n a();\n} catch (b) {\n c();\n} catch (d) {} finally {\n e();\n}');
// Comma-first option - (c0 = "\n, ", c1 = "\n , ", c2 = "\n , ", c3 = "\n , ")
opts.comma_first = true;
bt('{a:1, b:2}', '{\n a: 1\n , b: 2\n}');
@ -1390,7 +1419,50 @@ function run_javascript_tests(test_obj, Urlencoded, js_beautify, html_beautify,
// Destructured and related
opts.brace_style = 'collapse-preserve-inline';
// Issue 382 - import destructured
bt(
'module "Even" {\n' +
' import { odd, oddly } from "Odd";\n' +
'}');
// Issue 511 - destrutured
bt(
'var { b, c } = require("../stores");\n' +
'var { ProjectStore } = require("../stores");\n' +
'\n' +
'function takeThing({ prop }) {\n' +
' console.log("inner prop", prop)\n' +
'}');
// Issue 315 - Short objects
bt(
'var a = { b: { c: { d: e } } };');
bt(
'var a = {\n' +
' b: {\n' +
' c: { d: e }\n' +
' c3: { d: e }\n' +
' },\n' +
' b2: { c: { d: e } }\n' +
'};');
// Issue 370 - Short objects in array
bt(
'var methods = [\n' +
' { name: "to" },\n' +
' { name: "step" },\n' +
' { name: "move" },\n' +
' { name: "min" },\n' +
' { name: "max" }\n' +
'];');
// Old tests
opts.brace_style = 'collapse';
bt('');
test_fragment(' return .5');
test_fragment(' return .5;\n a();');

View File

@ -128,6 +128,7 @@ class BeautifierFlags:
self.declaration_statement = False
self.declaration_assignment = False
self.multiline_frame = False
self.inline_frame = False
self.if_block = False
self.else_block = False
self.do_block = False
@ -230,6 +231,7 @@ class Token:
self.wanted_newline = newlines > 0
self.whitespace_before = whitespace_before
self.parent = None
self.opened = None
self.directives = None
@ -288,7 +290,7 @@ Output options:
-E, --space-in-empty-paren Add a single space inside empty paren, ie. f( )
-j, --jslint-happy More jslint-compatible output
-a, --space_after_anon_function Add a space before an anonymous function's parens, ie. function ()
-b, --brace-style=collapse Brace style (collapse, expand, end-expand)
-b, --brace-style=collapse Brace style (collapse-preserve-inline, collapse, expand, end-expand)
-k, --keep-array-indentation Keep array indentation.
-r, --replace Write output in-place, replacing input
-o, --outfile=FILE Specify a file to output to (default stdout)
@ -381,8 +383,8 @@ class Beautifier:
if opts != None:
self.opts = copy.copy(opts)
if self.opts.brace_style not in ['expand', 'collapse', 'end-expand', 'none']:
raise(Exception('opts.brace_style must be "expand", "collapse", "end-expand", or "none".'))
if self.opts.brace_style not in ['expand', 'collapse', 'collapse-preserve-inline', 'end-expand', 'none']:
raise(Exception('opts.brace_style must be "expand", "collapse", "collapse-preserve-inline", "end-expand", or "none".'))
s = self.blank_state(s)
@ -738,9 +740,11 @@ class Beautifier:
else:
self.set_mode(MODE.BlockStatement)
elif self.last_type in ['TK_EQUALS', 'TK_START_EXPR', 'TK_COMMA', 'TK_OPERATOR'] or \
(self.last_type == 'TK_RESERVED' and self.flags.last_text in ['return', 'throw']):
# Detecting shorthand function syntax is difficult by scanning forward, so check the surrounding context.
# If the block is being returned, passed as arg, assigned with = or assigned in a nested object, treat as an ObjectLiteral.
(self.last_type == 'TK_RESERVED' and self.flags.last_text in ['return', 'throw', 'import']):
# Detecting shorthand function syntax is difficult by scanning forward,
# so check the surrounding context.
# If the block is being returned, imported, passed as arg,
# assigned with = or assigned in a nested object, treat as an ObjectLiteral.
self.set_mode(MODE.ObjectLiteral);
else:
self.set_mode(MODE.BlockStatement)
@ -759,18 +763,40 @@ class Beautifier:
else:
self.print_newline(preserve_statement_flags = True)
else: # collapse
if self.last_type not in ['TK_OPERATOR', 'TK_START_EXPR']:
if self.opts.brace_style == 'collapse-preserve-inline':
# search forward for newline wanted inside this block
index = 0
check_token = None
self.flags.inline_frame = True
do_loop = True
while (do_loop):
index += 1
check_token = self.get_token(index)
if check_token.wanted_newline:
self.flags.inline_frame = False
do_loop = (check_token.type != 'TK_EOF' and
not (check_token.type == 'TK_END_BLOCK' and check_token.opened == current_token))
if self.is_array(self.previous_flags.mode) and (self.last_type == 'TK_START_EXPR' or self.last_type == 'TK_COMMA'):
# if we're preserving inline,
# allow newline between comma and next brace.
if self.flags.inline_frame:
self.allow_wrap_or_preserved_newline(current_token)
self.flags.inline_frame = True
self.previous_flags.multiline_frame = self.previous_flags.multiline_frame or self.flags.multiline_frame
self.flags.multiline_frame = False
else:
self.output.space_before_token = self.last_type == 'TK_COMMA'
elif self.last_type not in ['TK_OPERATOR', 'TK_START_EXPR']:
if self.last_type == 'TK_START_BLOCK':
self.print_newline()
else:
self.output.space_before_token = True
else:
# if TK_OPERATOR or TK_START_EXPR
if self.is_array(self.previous_flags.mode) and self.flags.last_text == ',':
if self.last_last_text == '}':
self.output.space_before_token = True
else:
self.print_newline()
self.print_token(current_token)
self.indent()
@ -788,7 +814,9 @@ class Beautifier:
else:
# skip {}
if not empty_braces:
if self.is_array(self.flags.mode) and self.opts.keep_array_indentation:
if self.flags.inline_frame:
self.output.space_before_token = True
elif self.is_array(self.flags.mode) and self.opts.keep_array_indentation:
self.opts.keep_array_indentation = False
self.print_newline()
self.opts.keep_array_indentation = True
@ -891,7 +919,7 @@ class Beautifier:
prefix = 'NONE'
if self.last_type == 'TK_END_BLOCK':
if not (current_token.type == 'TK_RESERVED' and current_token.text in ['else', 'catch', 'finally']):
if not (current_token.type == 'TK_RESERVED' and current_token.text in ['else', 'catch', 'finally', 'from']):
prefix = 'NEWLINE'
else:
if self.opts.brace_style in ['expand', 'end-expand'] or \
@ -911,7 +939,10 @@ class Beautifier:
(self.flags.last_text == '*' and self.last_last_text == 'function'):
prefix = 'SPACE'
elif self.last_type == 'TK_START_BLOCK':
prefix = 'NEWLINE'
if self.flags.inline_frame:
prefix = 'SPACE'
else:
prefix = 'NEWLINE'
elif self.last_type == 'TK_END_EXPR':
self.output.space_before_token = True
prefix = 'NEWLINE'
@ -983,7 +1014,7 @@ class Beautifier:
# The conditional starts the statement if appropriate.
# One difference - strings want at least a space before
self.output.space_before_token = True
elif self.last_type == 'TK_RESERVED' or self.last_type == 'TK_WORD':
elif self.last_type == 'TK_RESERVED' or self.last_type == 'TK_WORD' or self.flags.inline_frame:
self.output.space_before_token = True
elif self.last_type in ['TK_COMMA', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR']:
if not self.start_of_object_property():
@ -1028,17 +1059,17 @@ class Beautifier:
return
self.print_token(current_token)
self.output.space_before_token = True
if self.flags.mode == MODE.ObjectLiteral \
or (self.flags.mode == MODE.Statement and self.flags.parent.mode == MODE.ObjectLiteral):
if self.flags.mode == MODE.Statement:
self.restore_mode()
self.print_newline()
if not self.flags.inline_frame:
self.print_newline()
else:
# EXPR or DO_BLOCK
self.output.space_before_token = True
# for comma-first, we want to allow a newline before the comma
# to turn into a newline after the comma, which we will fixup later
if self.opts.comma_first:
@ -1115,7 +1146,8 @@ class Beautifier:
if current_token.text in ['-', '+'] and self.flags.last_text in ['--', '++']:
space_after = True
if self.flags.mode == MODE.BlockStatement and self.flags.last_text in ['{', ';']:
if (((self.flags.mode == MODE.BlockStatement and not self.flags.inline_frame) or self.flags.mode == MODE.Statement)
and self.flags.last_text in ['{', ';']):
# { foo: --i }
# foo(): --bar
self.print_newline()
@ -1423,7 +1455,7 @@ class Tokenizer:
# 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(',')
reserved_words = line_starters + ['do', 'in', 'else', 'get', 'set', 'new', 'catch', 'finally', 'typeof', 'yield', 'async', 'await']
reserved_words = line_starters + ['do', 'in', 'else', 'get', 'set', 'new', 'catch', 'finally', 'typeof', 'yield', 'async', 'await', 'from']
def __init__ (self, input, opts, indent_string):
self.input = input
@ -1479,6 +1511,7 @@ class Tokenizer:
(next.text == ')' and open.text == '(') or \
(next.text == '}' and open.text == '{'))):
next.parent = open.parent
next.opened = open
open = open_stack.pop()
self.tokens.append(next)

View File

@ -93,6 +93,34 @@ class TestJSBeautifier(unittest.TestCase):
test_fragment(' \n\nreturn .5\n\n\n\n', ' return .5')
test_fragment('\n', '')
# Brace style permutations - (ibo = "", iao = "", ibc = "", iac = "", obo = " ", oao = " ", obc = " ", oac = " ")
self.options.brace_style = 'collapse-preserve-inline'
bt('var a ={a: 2};\nvar a ={a: 2};', 'var a = { a: 2 };\nvar a = { a: 2 };')
bt('//case 1\nif (a == 1){}\n//case 2\nelse if (a == 2){}', '//case 1\nif (a == 1) {}\n//case 2\nelse if (a == 2) {}')
bt('if(1){2}else{3}', 'if (1) { 2 } else { 3 }')
bt('try{a();}catch(b){c();}catch(d){}finally{e();}', 'try { a(); } catch (b) { c(); } catch (d) {} finally { e(); }')
# Brace style permutations - (ibo = "\n", iao = "\n", ibc = "\n", iac = "\n", obo = " ", oao = "\n ", obc = "\n", oac = " ")
self.options.brace_style = 'collapse-preserve-inline'
bt('var a =\n{\na: 2\n}\n;\nvar a =\n{\na: 2\n}\n;', 'var a = {\n a: 2\n};\nvar a = {\n a: 2\n};')
bt('//case 1\nif (a == 1)\n{}\n//case 2\nelse if (a == 2)\n{}', '//case 1\nif (a == 1) {}\n//case 2\nelse if (a == 2) {}')
bt('if(1)\n{\n2\n}\nelse\n{\n3\n}', 'if (1) {\n 2\n} else {\n 3\n}')
bt('try\n{\na();\n}\ncatch(b)\n{\nc();\n}\ncatch(d)\n{}\nfinally\n{\ne();\n}', 'try {\n a();\n} catch (b) {\n c();\n} catch (d) {} finally {\n e();\n}')
# Brace style permutations - (ibo = "", iao = "", ibc = "", iac = "", obo = " ", oao = "\n ", obc = "\n", oac = " ")
self.options.brace_style = 'collapse'
bt('var a ={a: 2};\nvar a ={a: 2};', 'var a = {\n a: 2\n};\nvar a = {\n a: 2\n};')
bt('//case 1\nif (a == 1){}\n//case 2\nelse if (a == 2){}', '//case 1\nif (a == 1) {}\n//case 2\nelse if (a == 2) {}')
bt('if(1){2}else{3}', 'if (1) {\n 2\n} else {\n 3\n}')
bt('try{a();}catch(b){c();}catch(d){}finally{e();}', 'try {\n a();\n} catch (b) {\n c();\n} catch (d) {} finally {\n e();\n}')
# Brace style permutations - (ibo = "\n", iao = "\n", ibc = "\n", iac = "\n", obo = " ", oao = "\n ", obc = "\n", oac = " ")
self.options.brace_style = 'collapse'
bt('var a =\n{\na: 2\n}\n;\nvar a =\n{\na: 2\n}\n;', 'var a = {\n a: 2\n};\nvar a = {\n a: 2\n};')
bt('//case 1\nif (a == 1)\n{}\n//case 2\nelse if (a == 2)\n{}', '//case 1\nif (a == 1) {}\n//case 2\nelse if (a == 2) {}')
bt('if(1)\n{\n2\n}\nelse\n{\n3\n}', 'if (1) {\n 2\n} else {\n 3\n}')
bt('try\n{\na();\n}\ncatch(b)\n{\nc();\n}\ncatch(d)\n{}\nfinally\n{\ne();\n}', 'try {\n a();\n} catch (b) {\n c();\n} catch (d) {} finally {\n e();\n}')
# Comma-first option - (c0 = "\n, ", c1 = "\n , ", c2 = "\n , ", c3 = "\n , ")
self.options.comma_first = true
bt('{a:1, b:2}', '{\n a: 1\n , b: 2\n}')
@ -1164,7 +1192,48 @@ class TestJSBeautifier(unittest.TestCase):
' }\n' +
'}.fn2()')
# Destructured and related
self.options.brace_style = 'collapse-preserve-inline'
# Issue 382 - import destructured
bt(
'module "Even" {\n' +
' import { odd, oddly } from "Odd";\n' +
'}')
# Issue 511 - destrutured
bt(
'var { b, c } = require("../stores");\n' +
'var { ProjectStore } = require("../stores");\n' +
'\n' +
'function takeThing({ prop }) {\n' +
' console.log("inner prop", prop)\n' +
'}')
# Issue 315 - Short objects
bt(
'var a = { b: { c: { d: e } } };')
bt(
'var a = {\n' +
' b: {\n' +
' c: { d: e }\n' +
' c3: { d: e }\n' +
' },\n' +
' b2: { c: { d: e } }\n' +
'};')
# Issue 370 - Short objects in array
bt(
'var methods = [\n' +
' { name: "to" },\n' +
' { name: "step" },\n' +
' { name: "move" },\n' +
' { name: "min" },\n' +
' { name: "max" }\n' +
'];')
# Old tests
self.options.brace_style = 'collapse'
bt('')
test_fragment(' return .5')
test_fragment(' return .5;\n a();')

View File

@ -63,6 +63,98 @@ exports.test_data = {
{ fragment: true, input: ' \n\nreturn .5\n\n\n\n', output: ' return .5{{eof}}' },
{ fragment: true, input: '\n', output: '{{eof}}' }
],
}, {
name: "Brace style permutations",
description: "",
template: "< >",
matrix: [
// collapse-preserve-inline variations
{
options: [
{ name: "brace_style", value: "'collapse-preserve-inline'" }
],
ibo: '',
iao: '',
ibc: '',
iac: '',
obo: ' ',
oao: ' ',
obc: ' ',
oac: ' '
},
{
options: [
{ name: "brace_style", value: "'collapse-preserve-inline'" }
],
ibo: '\\n',
iao: '\\n',
ibc: '\\n',
iac: '\\n',
obo: ' ',
oao: '\\n ',
obc: '\\n',
oac: ' '
},
// collapse variations
{
options: [
{ name: "brace_style", value: "'collapse'" }
],
ibo: '',
iao: '',
ibc: '',
iac: '',
obo: ' ',
oao: '\\n ',
obc: '\\n',
oac: ' '
},
{
options: [
{ name: "brace_style", value: "'collapse'" }
],
ibo: '\\n',
iao: '\\n',
ibc: '\\n',
iac: '\\n',
obo: ' ',
oao: '\\n ',
obc: '\\n',
oac: ' '
},
],
tests: [
{
input: 'var a =<ibo>{<iao>a: 2<ibc>}<iac>;\nvar a =<ibo>{<iao>a: 2<ibc>}<iac>;',
output: 'var a =<obo>{<oao>a: 2<obc>};\nvar a =<obo>{<oao>a: 2<obc>};'
},
// {
// input: 'var a =<ibo>{<iao>a:<ibo>{<iao>a:<ibo>{<iao>a:2<ibc>}<iac><ibc>}<iac>}<iac>;\nvar a =<ibo>{<iao>a:<ibo>{<iao>a:<ibo>{<iao>a:2<ibc>}<iac><ibc>}<iac>}<iac>;',
// output: 'var a =<obo>{<oao>a:<obo>{<oao>a:<obo>{<oao>a: 2<obc>}<oac><obc>}<oac><obc>};\nvar a =<obo>{<oao>a:<obo>{<oao>a:<obo>{<oao>a: 2<obc>}<oac><obc>}<oac><obc>};'
// },
{
input: '//case 1\nif (a == 1)<ibo>{}\n//case 2\nelse if (a == 2)<ibo>{}',
output: '//case 1\nif (a == 1)<obo>{}\n//case 2\nelse if (a == 2)<obo>{}'
},
{
input: 'if(1)<ibo>{<iao>2<ibc>}<iac>else<ibo>{<iao>3<ibc>}',
output: 'if (1)<obo>{<oao>2<obc>}<oac>else<obo>{<oao>3<obc>}'
},
{
input:
'try<ibo>{<iao>a();<ibc>}<iac>' +
'catch(b)<ibo>{<iao>c();<ibc>}<iac>' +
'catch(d)<ibo>{}<iac>' +
'finally<ibo>{<iao>e();<ibc>}',
output:
// expected
'try<obo>{<oao>a();<obc>}<oac>' +
'catch (b)<obo>{<oao>c();<obc>}<oac>' +
'catch (d)<obo>{}<oac>'+
'finally<obo>{<oao>e();<obc>}'
}
],
}, {
name: "Comma-first option",
description: "Put commas at the start of lines instead of the end",
@ -1330,6 +1422,72 @@ exports.test_data = {
]
}
]
}, {
name: "Destructured and related",
description: "Ensure specific bugs do not recur",
options: [{ name: "brace_style", value: "'collapse-preserve-inline'" }],
tests: [
{
comment: "Issue 382 - import destructured ",
unchanged: [
'module "Even" {',
' import { odd, oddly } from "Odd";',
'}' ]
},
{
comment: "Issue 511 - destrutured ",
unchanged: [
'var { b, c } = require("../stores");',
'var { ProjectStore } = require("../stores");',
'',
'function takeThing({ prop }) {',
' console.log("inner prop", prop)',
'}'
]
},
{
comment: "Issue 315 - Short objects ",
unchanged: [
'var a = { b: { c: { d: e } } };'
]
},
{
unchanged: [
'var a = {',
' b: {',
' c: { d: e }',
' c3: { d: e }',
' },',
' b2: { c: { d: e } }',
'};'
]
},
{
comment: "Issue 370 - Short objects in array",
unchanged: [
'var methods = [',
' { name: "to" },',
' { name: "step" },',
' { name: "move" },',
' { name: "min" },',
' { name: "max" }',
'];'
]
},
// {
// comment: "Issue #338 - Short expressions ",
// unchanged: [
// 'if(someCondition) { return something; }',
// 'if(someCondition) {',
// ' return something;',
// '}',
// 'if(someCondition) { return something; }',
// 'if(someCondition) {',
// ' return something;',
// '}'
// ]
// },
]
},
// =======================================================
@ -1340,7 +1498,7 @@ exports.test_data = {
{
name: "Old tests",
description: "Largely unorganized pile of tests",
options: [],
options: [{ name: "brace_style", value: "'collapse'" }],
tests: [
{ unchanged: '' },
{ fragment: true, unchanged: ' return .5'},