Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for keywords as IdentifierNames such as .catch() #439

Merged
merged 1 commit into from
Mar 28, 2014
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
82 changes: 44 additions & 38 deletions js/lib/beautify.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
var input, output_lines;
var token_text, token_type, last_type, last_last_text, indent_string;
var flags, previous_flags, flag_store;
var whitespace, wordchar, punct, parser_pos, line_starters, digits;
var whitespace, wordchar, punct, parser_pos, line_starters, reserved_words, digits;
var prefix;
var input_wanted_newline;
var output_wrapped, output_space_before_token;
Expand All @@ -104,6 +104,8 @@

// words which should always start on new line.
line_starters = 'continue,try,throw,return,var,let,const,if,switch,case,default,for,while,break,function'.split(',');
reserved_words = line_starters.concat(['do', 'in', 'else', 'get', 'set', 'new', 'catch', 'finally', 'typeof']);


MODE = {
BlockStatement: 'BlockStatement', // 'BLOCK'
Expand All @@ -121,6 +123,7 @@
'TK_START_BLOCK': handle_start_block,
'TK_END_BLOCK': handle_end_block,
'TK_WORD': handle_word,
'TK_RESERVED': handle_word,
'TK_SEMICOLON': handle_semicolon,
'TK_STRING': handle_string,
'TK_EQUALS': handle_equals,
Expand Down Expand Up @@ -553,14 +556,14 @@

function start_of_statement() {
if (
(flags.last_text === 'do' ||
(flags.last_text === 'else' && token_text !== 'if') ||
((last_type === 'TK_RESERVED' && flags.last_text === 'do') ||
(last_type === 'TK_RESERVED' && flags.last_text === 'else' && !(token_type === 'TK_RESERVED' && token_text === 'if')) ||
(last_type === 'TK_END_EXPR' && (previous_flags.mode === MODE.ForInitializer || previous_flags.mode === MODE.Conditional)))) {
// Issue #276:
// If starting a new statement with [if, for, while, do], push to a new line.
// if (a) if (b) if(c) d(); else e(); else f();
allow_wrap_or_preserved_newline(
in_array(token_text, ['do', 'for', 'if', 'while']));
token_type === 'TK_RESERVED' && in_array(token_text, ['do', 'for', 'if', 'while']));

set_mode(MODE.Statement);
// Issue #275:
Expand Down Expand Up @@ -733,8 +736,11 @@
return [c, 'TK_WORD'];
}

if (c === 'in') { // hack for 'in' operator
return [c, 'TK_OPERATOR'];
if (last_type !== 'TK_DOT' && in_array(c, reserved_words)) {
if (c === 'in') { // hack for 'in' operator
return [c, 'TK_OPERATOR'];
}
return [c, 'TK_RESERVED'];
}
return [c, 'TK_WORD'];
}
Expand Down Expand Up @@ -806,7 +812,7 @@
(c === '/') || // regexp
(opt.e4x && c === "<" && input.slice(parser_pos - 1).match(/^<([-a-zA-Z:0-9_.]+|{[^{}]*}|!\[CDATA\[[\s\S]*?\]\])\s*([-a-zA-Z:0-9_.]+=('[^']*'|"[^"]*"|{[^{}]*})\s*)*\/?\s*>/)) // xml
) && ( // regex and xml can only appear in specific locations during parsing
(last_type === 'TK_WORD' && is_special_word(flags.last_text)) ||
(last_type === 'TK_RESERVED' && is_special_word(flags.last_text)) ||
(last_type === 'TK_END_EXPR' && in_array(previous_flags.mode, [MODE.Conditional, MODE.ForInitializer])) ||
(in_array(last_type, ['TK_COMMENT', 'TK_START_EXPR', 'TK_START_BLOCK',
'TK_END_BLOCK', 'TK_OPERATOR', 'TK_EQUALS', 'TK_EOF', 'TK_SEMICOLON', 'TK_COMMA'
Expand Down Expand Up @@ -1006,10 +1012,10 @@
var next_mode = MODE.Expression;
if (token_text === '[') {

if (last_type === 'TK_WORD' || flags.last_text === ')') {
if (last_type === 'TK_WORD' || last_type === 'TK_RESERVED' || flags.last_text === ')') {
// this is array index specifier, break immediately
// a[x], fn()[x]
if (in_array(flags.last_text, line_starters)) {
if (last_type === 'TK_RESERVED' && in_array(flags.last_text, line_starters)) {
output_space_before_token = true;
}
set_mode(next_mode);
Expand All @@ -1034,9 +1040,9 @@
}

} else {
if (flags.last_text === 'for') {
if (last_type === 'TK_RESERVED' && flags.last_text === 'for') {
next_mode = MODE.ForInitializer;
} else if (in_array(flags.last_text, ['if', 'while'])) {
} else if (last_type === 'TK_RESERVED' && in_array(flags.last_text, ['if', 'while'])) {
next_mode = MODE.Conditional;
} else {
// next_mode = MODE.Expression;
Expand All @@ -1050,14 +1056,14 @@
allow_wrap_or_preserved_newline(input_wanted_newline);
output_wrapped = false;
// do nothing on (( and )( and ][ and ]( and .(
} else if (last_type !== 'TK_WORD' && last_type !== 'TK_OPERATOR') {
} else if (last_type !== 'TK_RESERVED' && last_type !== 'TK_WORD' && last_type !== 'TK_OPERATOR') {
output_space_before_token = true;
} else if (flags.last_word === 'function' || flags.last_word === 'typeof') {
} else if (last_type === 'TK_RESERVED' && (flags.last_word === 'function' || flags.last_word === 'typeof')) {
// function() vs function ()
if (opt.jslint_happy) {
output_space_before_token = true;
}
} else if (in_array(flags.last_text, line_starters) || flags.last_text === 'catch') {
} else if (last_type === 'TK_RESERVED' && (in_array(flags.last_text, line_starters) || flags.last_text === 'catch')) {
if (opt.space_before_conditional) {
output_space_before_token = true;
}
Expand Down Expand Up @@ -1136,7 +1142,7 @@
if (last_type !== 'TK_OPERATOR' &&
(empty_anonymous_function ||
last_type === 'TK_EQUALS' ||
(is_special_word(flags.last_text) && flags.last_text !== 'else'))) {
(last_type === 'TK_RESERVED' && is_special_word(flags.last_text) && flags.last_text !== 'else'))) {
output_space_before_token = true;
} else {
print_newline();
Expand Down Expand Up @@ -1199,13 +1205,13 @@
} else if (input_wanted_newline && !is_expression(flags.mode) &&
(last_type !== 'TK_OPERATOR' || (flags.last_text === '--' || flags.last_text === '++')) &&
last_type !== 'TK_EQUALS' &&
(opt.preserve_newlines || !in_array(flags.last_text, ['var', 'let', 'const']))) {
(opt.preserve_newlines || !(last_type === 'TK_RESERVED' && in_array(flags.last_text, ['var', 'let', 'const'])))) {

print_newline();
}

if (flags.do_block && !flags.do_while) {
if (token_text === 'while') {
if (token_type === 'TK_RESERVED' && token_text === 'while') {
// do {} ## while ()
output_space_before_token = true;
print_token();
Expand All @@ -1224,15 +1230,15 @@
// Bare/inline ifs are tricky
// Need to unwind the modes correctly: if (a) if (b) c(); else d(); else e();
if (flags.if_block) {
if (token_text !== 'else') {
if (!(token_type === 'TK_RESERVED' && token_text === 'else')) {
while (flags.mode === MODE.Statement) {
restore_mode();
}
flags.if_block = false;
}
}

if (token_text === 'case' || (token_text === 'default' && flags.in_case_statement)) {
if (token_type === 'TK_RESERVED' && (token_text === 'case' || (token_text === 'default' && flags.in_case_statement))) {
print_newline();
if (flags.case_body || opt.jslint_happy) {
// switch cases following one another
Expand All @@ -1245,7 +1251,7 @@
return;
}

if (token_text === 'function') {
if (token_type === 'TK_RESERVED' && token_text === 'function') {
if (flags.var_line && last_type !== 'TK_EQUALS') {
flags.var_line_reindented = true;
}
Expand All @@ -1257,8 +1263,8 @@
print_newline(true);
}
}
if (last_type === 'TK_WORD') {
if (flags.last_text === 'get' || flags.last_text === 'set' || flags.last_text === 'new' || flags.last_text === 'return') {
if (last_type === 'TK_RESERVED' || last_type === 'TK_WORD') {
if (last_type === 'TK_RESERVED' && in_array(flags.last_text, ['get', 'set', 'new', 'return'])) {
output_space_before_token = true;
} else {
print_newline();
Expand All @@ -1279,7 +1285,7 @@
}
}

if (token_text === 'function') {
if (token_type === 'TK_RESERVED' && token_text === 'function') {
print_token();
flags.last_word = token_text;
return;
Expand All @@ -1288,7 +1294,7 @@
prefix = 'NONE';

if (last_type === 'TK_END_BLOCK') {
if (!in_array(token_text, ['else', 'catch', 'finally'])) {
if (!(token_type === 'TK_RESERVED' && in_array(token_text, ['else', 'catch', 'finally']))) {
prefix = 'NEWLINE';
} else {
if (opt.brace_style === "expand" || opt.brace_style === "end-expand") {
Expand All @@ -1305,7 +1311,7 @@
prefix = 'SPACE';
} else if (last_type === 'TK_STRING') {
prefix = 'NEWLINE';
} else if (last_type === 'TK_WORD') {
} else if (last_type === 'TK_RESERVED' || last_type === 'TK_WORD') {
prefix = 'SPACE';
} else if (last_type === 'TK_START_BLOCK') {
prefix = 'NEWLINE';
Expand All @@ -1314,7 +1320,7 @@
prefix = 'NEWLINE';
}

if (in_array(token_text, line_starters) && flags.last_text !== ')') {
if (token_type === 'TK_RESERVED' && in_array(token_text, line_starters) && flags.last_text !== ')') {
if (flags.last_text === 'else') {
prefix = 'SPACE';
} else {
Expand All @@ -1323,7 +1329,7 @@

}

if (in_array(token_text, ['else', 'catch', 'finally'])) {
if (token_type === 'TK_RESERVED' && in_array(token_text, ['else', 'catch', 'finally'])) {
if (last_type !== 'TK_END_BLOCK' || opt.brace_style === "expand" || opt.brace_style === "end-expand") {
print_newline();
} else {
Expand All @@ -1337,13 +1343,13 @@
output_space_before_token = true;
}
} else if (prefix === 'NEWLINE') {
if (is_special_word(flags.last_text)) {
if (last_type === 'TK_RESERVED' && is_special_word(flags.last_text)) {
// no newline between 'return nnn'
output_space_before_token = true;
} else if (last_type !== 'TK_END_EXPR') {
if ((last_type !== 'TK_START_EXPR' || !in_array(token_text, ['var', 'let', 'const'])) && flags.last_text !== ':') {
if ((last_type !== 'TK_START_EXPR' || !(token_type === 'TK_RESERVED' && in_array(token_text, ['var', 'let', 'const']))) && flags.last_text !== ':') {
// no need to force newline on 'var': for (var x = 0...)
if (token_text === 'if' && flags.last_word === 'else' && flags.last_text !== '{') {
if (token_type === 'TK_RESERVED' && token_text === 'if' && flags.last_word === 'else' && flags.last_text !== '{') {
// no newline for } else if {
output_space_before_token = true;
} else {
Expand All @@ -1352,7 +1358,7 @@
print_newline();
}
}
} else if (in_array(token_text, line_starters) && flags.last_text !== ')') {
} else if (token_type === 'TK_RESERVED' && in_array(token_text, line_starters) && flags.last_text !== ')') {
flags.var_line = false;
flags.var_line_reindented = false;
print_newline();
Expand All @@ -1365,17 +1371,17 @@
print_token();
flags.last_word = token_text;

if (in_array(token_text, ['var', 'let', 'const'])) {
if (token_type === 'TK_RESERVED' && in_array(token_text, ['var', 'let', 'const'])) {
flags.var_line = true;
flags.var_line_reindented = false;
flags.var_line_tainted = false;
}

if (token_text === 'do') {
if (token_type === 'TK_RESERVED' && token_text === 'do') {
flags.do_block = true;
}

if (token_text === 'if') {
if (token_type === 'TK_RESERVED' && token_text === 'if') {
flags.if_block = true;
}
}
Expand Down Expand Up @@ -1404,7 +1410,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_WORD') {
} else if (last_type === 'TK_RESERVED' || last_type === 'TK_WORD') {
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()) {
Expand Down Expand Up @@ -1470,7 +1476,7 @@
function handle_operator() {
var space_before = true;
var space_after = true;
if (is_special_word(flags.last_text)) {
if (last_type === 'TK_RESERVED' && is_special_word(flags.last_text)) {
// "return" had a special handling in TK_WORD. Now we need to return the favor
output_space_before_token = true;
print_token();
Expand Down Expand Up @@ -1516,7 +1522,7 @@
space_before = true;
}

if (last_type === 'TK_WORD' && in_array(flags.last_text, line_starters)) {
if (last_type === 'TK_RESERVED') {
space_before = true;
}

Expand Down Expand Up @@ -1591,7 +1597,7 @@
}

function handle_dot() {
if (is_special_word(flags.last_text)) {
if (last_type === 'TK_RESERVED' && is_special_word(flags.last_text)) {
output_space_before_token = true;
} else {
// allow preserved newlines before dots in general
Expand Down
6 changes: 6 additions & 0 deletions js/test/beautify-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,12 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify,
// a common snippet in jQuery plugins
bt("settings = $.extend({},defaults,settings);", "settings = $.extend({}, defaults, settings);");

// reserved words used as property names
bt("$http().then().finally().default()", "$http().then().finally().default()");
bt("$http()\n.then()\n.finally()\n.default()", "$http()\n .then()\n .finally()\n .default()");
bt("$http().when.in.new.catch().throw()", "$http().when.in.new.catch().throw()");
bt("$http()\n.when\n.in\n.new\n.catch()\n.throw()", "$http()\n .when\n .in\n .new\n .catch()\n .throw()");

bt('{xxx;}()', '{\n xxx;\n}()');

bt("a = 'a'\nb = 'b'");
Expand Down
Loading