Implement flags.had_comment, fix #329, fix #291

We deliberately lose token_type = TK_COMMENT and TK_INLINE_COMMENT to
allow their transparent handling. To counteract this, flags.had_comment
counter-spell is implemented, so that we had a possibility to know that
there was, in fact, a comment somewhere.

Thus, we can fix some corner-cases where an unexpected comment might
break the structure.
This commit is contained in:
Einar Lielmanis 2013-10-11 06:36:35 +03:00
parent 33082bda27
commit d953b6751b
4 changed files with 29 additions and 7 deletions

View File

@ -163,6 +163,7 @@
indentation_level: next_indent_level,
line_indent_level: flags_base ? flags_base.line_indent_level : next_indent_level,
start_line_index: output_lines.length,
had_comment: false,
ternary_depth: 0
}
return next_flags;
@ -296,6 +297,8 @@
last_type = token_type;
flags.last_text = token_text;
}
flags.had_comment = (token_type === 'TK_INLINE_COMMENT' || token_type === 'TK_COMMENT'
|| token_type === 'TK_BLOCK_COMMENT');
}
@ -1245,11 +1248,10 @@
if (flags.var_line && last_type !== 'TK_EQUALS') {
flags.var_line_reindented = true;
}
if ((just_added_newline() || flags.last_text === ';' || flags.last_text === '}') &&
flags.last_text !== '{' && !is_array(flags.mode)) {
if (in_array(flags.last_text, ['}', ';']) || (just_added_newline() && ! in_array(flags.last_text, ['{', ':', '=', ',']))) {
// make sure there is a nice clean space of at least one blank line
// before a new function definition, except in arrays
if (!just_added_blankline()) {
// before a new function definition
if ( ! just_added_blankline() && ! flags.had_comment) {
print_newline();
print_newline(true);
}

View File

@ -1297,6 +1297,14 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify)
bt('(if(a) b())\n\n\n(if(a) b())',
'(\n if (a) b())\n\n\n(\n if (a) b())');
// space between functions
bt('/*\n * foo\n */\nfunction foo() {}');
bt('// a nice function\nfunction foo() {}');
bt('function foo() {}\nfunction foo() {}',
'function foo() {}\n\nfunction foo() {}'
);
bt("if\n(a)\nb();", "if (a)\n b();");
bt('var a =\nfoo', 'var a =\n foo');
@ -1364,6 +1372,7 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify)
bt('xml=<![CDATA[ b="c"><d/><e v={z}>\n foo</e>x/]]>;', 'xml = <![CDATA[ b="c"><d/><e v={z}>\n foo</e>x/]]>;');
bt('xml=<![CDATA[]]>;', 'xml = <![CDATA[]]>;');
bt('xml=<a b="c"><![CDATA[d/></a></{}]]></a>;', 'xml = <a b="c"><![CDATA[d/></a></{}]]></a>;');
// Handles messed up tags, as long as it isn't the same name
// as the root tag. Also handles tags of same name as root tag
// as long as nesting matches.

View File

@ -127,6 +127,7 @@ class BeautifierFlags:
self.line_indent_level = 0
self.start_line_index = 0
self.ternary_depth = 0
self.had_comment = False
def apply_base(self, flags_base, added_newline):
next_indent_level = flags_base.indentation_level;
@ -332,6 +333,7 @@ class Beautifier:
self.last_last_text = self.flags.last_text
self.last_type = token_type
self.flags.last_text = self.token_text
self.flags.had_comment = token_type in ['TK_COMMENT', 'TK_INLINE_COMMENT', 'TK_BLOCK_COMMENT']
sweet_code = ''.join(self.output_lines[0].text)
if len(self.output_lines) > 1:
@ -1063,11 +1065,11 @@ class Beautifier:
if token_text == 'function':
if self.flags.var_line and self.flags.last_text != '=':
self.flags.var_line_reindented = not self.opts.keep_function_indentation
if (self.just_added_newline() or self.flags.last_text == ';' or self.flags.last_text == '}') and \
self.flags.last_text != '{' and not self.is_array(self.flags.mode):
if self.flags.last_text in ['}', ';'] or (self.just_added_newline() and not self.flags.last_text in ['{', ':', '=', ',']):
# make sure there is a nice clean space of at least one blank line
# before a new function definition, except in arrays
if not self.just_added_blankline():
if not self.just_added_blankline() and not self.flags.had_comment:
self.append_newline()
self.append_newline(True)

View File

@ -1112,6 +1112,15 @@ class TestJSBeautifier(unittest.TestCase):
bt('(if(a) b())\n\n\n(if(a) b())',
'(\n if (a) b())\n(\n if (a) b())');
# space between functions
bt('/*\n * foo\n */\nfunction foo() {}');
bt('// a nice function\nfunction foo() {}');
bt('function foo() {}\nfunction foo() {}',
'function foo() {}\n\nfunction foo() {}'
);
bt("if\n(a)\nb();", "if (a) b();");
bt('var a =\nfoo', 'var a = foo');
bt('var a = {\n"a":1,\n"b":2}', "var a = {\n \"a\": 1,\n \"b\": 2\n}");