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

Tab and space alignment correction #1572

Merged
merged 10 commits into from
Dec 6, 2018
Merged
14 changes: 12 additions & 2 deletions js/src/core/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,20 @@ function Options(options, merge_child_field) {
this.max_preserve_newlines = 0;
}

this.indent_with_tabs = this._get_boolean('indent_with_tabs');
this.indent_with_tabs = this._get_boolean('indent_with_tabs', this.indent_char === '\t');
if (this.indent_with_tabs) {
this.indent_char = '\t';
this.indent_size = 1;

// indent_size behavior changed after 1.8.6
// It used to be that indent_size would be
// set to 1 for indent_with_tabs. That is no longer needed and
// actually doesn't make sense - why not use spaces? Further,
// that might produce unexpected behavior - tabs being used
// for single-column alignment. So, when indent_with_tabs is true
// and indent_size is 1, reset indent_size to 4.
if (this.indent_size === 1) {
this.indent_size = 4;
}
}

// Backwards compat with 1.3.x
Expand Down
100 changes: 63 additions & 37 deletions js/src/core/output.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/*jshint node:true */
/*

The MIT License (MIT)

Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
Expand Down Expand Up @@ -58,7 +57,7 @@ OutputLine.prototype.has_match = function(pattern) {
OutputLine.prototype.set_indent = function(indent, alignment) {
this.__indent_count = indent || 0;
this.__alignment_count = alignment || 0;
this.__character_count = this.__parent.baseIndentLength + this.__alignment_count + this.__indent_count * this.__parent.indent_length;
this.__character_count = this.__parent.get_indent_size(this.__indent_count, this.__alignment_count);
};

OutputLine.prototype.get_character_count = function() {
Expand Down Expand Up @@ -102,7 +101,7 @@ OutputLine.prototype.pop = function() {
OutputLine.prototype.remove_indent = function() {
if (this.__indent_count > 0) {
this.__indent_count -= 1;
this.__character_count -= this.__parent.indent_length;
this.__character_count -= this.__parent.indent_size;
}
};

Expand All @@ -116,53 +115,81 @@ OutputLine.prototype.trim = function() {
OutputLine.prototype.toString = function() {
var result = '';
if (!this.is_empty()) {
if (this.__indent_count >= 0) {
result = this.__parent.get_indent_string(this.__indent_count);
}
if (this.__alignment_count >= 0) {
result += this.__parent.get_alignment_string(this.__alignment_count);
}
result = this.__parent.get_indent_string(this.__indent_count, this.__alignment_count);
result += this.__items.join('');
}
return result;
};

function IndentCache(base_string, level_string) {
this.__cache = [base_string];
this.__level_string = level_string;
function IndentStringCache(options, baseIndentString) {
this.__cache = [''];
this.__indent_size = options.indent_size;
this.__indent_string = options.indent_char;
if (!options.indent_with_tabs) {
this.__indent_string = new Array(options.indent_size + 1).join(options.indent_char);
}

// Set to null to continue support for auto detection of base indent
baseIndentString = baseIndentString || '';
if (options.indent_level > 0) {
baseIndentString = new Array(options.indent_level + 1).join(this.__indent_string);
}

this.__base_string = baseIndentString;
this.__base_string_length = baseIndentString.length;
}

IndentCache.prototype.__ensure_cache = function(level) {
while (level >= this.__cache.length) {
this.__cache.push(this.__cache[this.__cache.length - 1] + this.__level_string);
IndentStringCache.prototype.get_indent_size = function(indent, column) {
var result = this.__base_string_length;
column = column || 0;
if (indent < 0) {
result = 0;
}
result += indent * this.__indent_size;
result += column;
return result;
};

IndentCache.prototype.get_level_string = function(level) {
this.__ensure_cache(level);
return this.__cache[level];
IndentStringCache.prototype.get_indent_string = function(indent_level, column) {
var result = this.__base_string;
column = column || 0;
if (indent_level < 0) {
indent_level = 0;
result = '';
}
column += indent_level * this.__indent_size;
this.__ensure_cache(column);
result += this.__cache[column];
return result;
};


function Output(options, baseIndentString) {
var indent_string = options.indent_char;
if (options.indent_size > 1) {
indent_string = new Array(options.indent_size + 1).join(options.indent_char);
IndentStringCache.prototype.__ensure_cache = function(column) {
while (column >= this.__cache.length) {
this.__add_column();
}
};

// Set to null to continue support for auto detection of base indent level.
baseIndentString = baseIndentString || '';
if (options.indent_level > 0) {
baseIndentString = new Array(options.indent_level + 1).join(indent_string);
IndentStringCache.prototype.__add_column = function() {
var column = this.__cache.length;
var indent = 0;
var result = '';
if (this.__indent_size && column >= this.__indent_size) {
indent = Math.floor(column / this.__indent_size);
column -= indent * this.__indent_size;
result = new Array(indent + 1).join(this.__indent_string);
}
if (column) {
result += new Array(column + 1).join(' ');
}

this.__cache.push(result);
};

this.__indent_cache = new IndentCache(baseIndentString, indent_string);
this.__alignment_cache = new IndentCache('', ' ');
this.baseIndentLength = baseIndentString.length;
this.indent_length = indent_string.length;
function Output(options, baseIndentString) {
this.__indent_cache = new IndentStringCache(options, baseIndentString);
this.raw = false;
this._end_with_newline = options.end_with_newline;

this.indent_size = options.indent_size;
this.__lines = [];
this.previous_line = null;
this.current_line = null;
Expand All @@ -181,12 +208,12 @@ Output.prototype.get_line_number = function() {
return this.__lines.length;
};

Output.prototype.get_indent_string = function(level) {
return this.__indent_cache.get_level_string(level);
Output.prototype.get_indent_string = function(indent, column) {
return this.__indent_cache.get_indent_string(indent, column);
};

Output.prototype.get_alignment_string = function(level) {
return this.__alignment_cache.get_level_string(level);
Output.prototype.get_indent_size = function(indent, column) {
return this.__indent_cache.get_indent_size(indent, column);
};

Output.prototype.is_empty = function() {
Expand Down Expand Up @@ -219,7 +246,6 @@ Output.prototype.get_code = function(eol) {
if (eol !== '\n') {
sweet_code = sweet_code.replace(/[\n]/g, eol);
}

return sweet_code;
};

Expand Down
1 change: 0 additions & 1 deletion js/src/html/beautifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,6 @@ Beautifier.prototype._handle_tag_open = function(printer, raw_token, last_tag_to
parser_token.alignment_size = raw_token.text.length + 1;
}


if (!parser_token.tag_complete && !parser_token.is_unformatted) {
printer.alignment_size = parser_token.alignment_size;
}
Expand Down
44 changes: 28 additions & 16 deletions js/src/javascript/beautifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ Beautifier.prototype.create_flags = function(flags_base, mode) {
in_case: false, // we're on the exact line with "case 0:"
case_body: false, // the indented case-action block
indentation_level: next_indent_level,
alignment: 0,
line_indent_level: flags_base ? flags_base.line_indent_level : next_indent_level,
start_line_index: this._output.get_line_number(),
ternary_depth: 0
Expand Down Expand Up @@ -393,7 +394,7 @@ Beautifier.prototype.print_token_line_indentation = function(current_token) {
if (this._options.keep_array_indentation && is_array(this._flags.mode) && current_token.newlines) {
this._output.current_line.push(current_token.whitespace_before);
this._output.space_before_token = false;
} else if (this._output.set_indent(this._flags.indentation_level)) {
} else if (this._output.set_indent(this._flags.indentation_level, this._flags.alignment)) {
this._flags.line_indent_level = this._flags.indentation_level;
}
}
Expand Down Expand Up @@ -1329,29 +1330,40 @@ Beautifier.prototype.handle_block_comment = function(current_token, preserve_sta

// block comment starts with a new line
this.print_newline(false, preserve_statement_flags);
if (lines.length > 1) {
javadoc = all_lines_start_with(lines.slice(1), '*');
starless = each_line_matches_indent(lines.slice(1), lastIndent);
}

// first line always indented
this.print_token(current_token, lines[0]);
for (j = 1; j < lines.length; j++) {
this.print_newline(false, true);


if (lines.length > 1) {
lines = lines.slice(1);
javadoc = all_lines_start_with(lines, '*');
starless = each_line_matches_indent(lines, lastIndent);

if (javadoc) {
// javadoc: reformat and re-indent
this.print_token(current_token, ' ' + ltrim(lines[j]));
} else if (starless && lines[j].length > lastIndentLength) {
// starless: re-indent non-empty content, avoiding trim
this.print_token(current_token, lines[j].substring(lastIndentLength));
} else {
// normal comments output raw
this._output.add_token(lines[j]);
this._flags.alignment = 1;
}

for (j = 0; j < lines.length; j++) {
this.print_newline(false, true);
if (javadoc) {
// javadoc: reformat and re-indent
this.print_token(current_token, ltrim(lines[j]));
} else if (starless && lines[j]) {
// starless: re-indent non-empty content, avoiding trim
this.print_token(current_token, lines[j].substring(lastIndentLength));
} else {
// normal comments output raw
this._output.add_token(lines[j]);
}
}

this._flags.alignment = 0;
}

// for comments of more than one line, make sure there's a new line after
// for comments on their own line or more than one line, make sure there's a new line after
this.print_newline(false, preserve_statement_flags);

};

Beautifier.prototype.handle_comment = function(current_token, preserve_statement_flags) {
Expand Down
Loading