Skip to content
This repository has been archived by the owner on Mar 23, 2024. It is now read-only.

Support autofix for disallow-trailing-whitespace #1480

Closed
wants to merge 1 commit into from
Closed
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
86 changes: 81 additions & 5 deletions lib/rules/disallow-trailing-whitespace.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,89 @@ module.exports.prototype = {

check: function(file, errors) {
var ignoreEmptyLines = this._ignoreEmptyLines;
var lineTokens = file._tokensByLineIndex;
var lines = file.getLines().length;
var lastLine = 1;

var lines = file.getLines();
for (var i = 0, l = lines.length; i < l; i++) {
if (lines[i].match(/\s$/) && !(ignoreEmptyLines && lines[i].match(/^\s*$/))) {
errors.add('Illegal trailing whitespace', i + 1, lines[i].length);
function checkTokenWhiteSpace(token) {
var whitespace = token.whitespaceBefore;
var subLines = whitespace.split(file.getLineBreakStyle());

for (var l = 0; l < subLines.length; l++) {
var subLine = subLines[l];

if (l === subLines.length - 1 && token.type !== 'EOF') {
// skip check if it is a last whitespace line and not eof
break;
}

var isEmptyLine =
l || // not first sub line (since there's prev tokens on line)
token._tokenIndex === 0 && l === 0 // first token exception
;

if (subLine.length && !(ignoreEmptyLines && isEmptyLine)) {
errors.assert.emit('error', {
message: 'Illegal trailing whitespace',
line: lastLine + l,
column: subLine.length,
fixed: true
});
subLines[l] = '';
}
}

token.whitespaceBefore = subLines.join(file.getLineBreakStyle());
}
}

for (var i = 1; i <= lines; i++) {
if (!lineTokens[i]) {
continue;
}

var line = lineTokens[i];
// check first line token
var token = line[0];
checkTokenWhiteSpace(token);

// check last line token
token = line[line.length - 1];
if (token.isComment && token.type === 'Line') {
// line comment
if (token.value.match(/\s+$/)) {
errors.assert.emit('error', {
message: 'Illegal trailing whitespace',
line: i,
column: token.loc.end.column,
fixed: true
});

token.value = token.value.replace(/\s+$/, '');
}
} else if (token.isComment && token.type === 'Block') {
// block comment
var subLines = token.value.split(file.getLineBreakStyle());
for (var l = 0; l < subLines.length - 1; l++) {
var subLine = subLines[l];

if (subLine.match(/\s$/) && !(ignoreEmptyLines && l && subLine.match(/^\s*$/))) {
errors.assert.emit('error', {
message: 'Illegal trailing whitespace',
line: i + l,
column: subLine.length,
fixed: true
});

subLines[l] = subLine.replace(/\s+$/, '');
}
}
token.value = subLines.join(file.getLineBreakStyle());
} else if (token.type === 'EOF') {
// non new line eof
checkTokenWhiteSpace(token);
}

lastLine = i;
}
}
};
3 changes: 2 additions & 1 deletion presets/mdcs.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@
"beforeConsequent": true,
"afterConsequent": true,
"beforeAlternate": true
}
},
"disallowTrailingWhitespace": true
}
59 changes: 59 additions & 0 deletions test/specs/rules/disallow-trailing-whitespace.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var Checker = require('../../../lib/checker');
var assert = require('assert');
var reportAndFix = require('../../lib/assertHelpers').reportAndFix;

describe('rules/disallow-trailing-whitespace', function() {
var checker;
Expand Down Expand Up @@ -37,6 +38,22 @@ describe('rules/disallow-trailing-whitespace', function() {
it('should not report when there is no trailing whitespace', function() {
assert(checker.checkString('var x;').isEmpty());
});

it('should report when there is trailing whitespace in line comment', function() {
assert(checker.checkString('// x \n').getErrorCount() === 1);
});

it('should report when there is trailing whitespace in block comment', function() {
assert(checker.checkString('/*\n *\n \t\n */').getErrorCount() === 1);
});

it('should not report trailing spaces the last line of block comment', function() {
assert(checker.checkString('/*\n\n */').isEmpty());
});

it('should report trailing whitespace on the first empty line', function() {
assert(checker.checkString('\t\n// eof').getErrorCount() === 1);
});
});

describe('ignoreEmptyLines', function() {
Expand All @@ -47,6 +64,48 @@ describe('rules/disallow-trailing-whitespace', function() {
it('should not report trailing whitespace on empty lines', function() {
assert(checker.checkString('if(a){\n\tb=c;\n\t\n}').isEmpty());
});

it('should not report trailing whitespace on empty lines in block comments', function() {
assert(checker.checkString('/*\n *\n \t\n */').isEmpty());
});

it('should not report trailing whitespace on the first empty line', function() {
assert(checker.checkString('\t\n//').isEmpty());
});
});

reportAndFix({
name: 'should fix trailing space (simple case)',
rules: { disallowTrailingWhitespace: true },
input: 'var x; ',
output: 'var x;'
});

reportAndFix({
name: 'should fix trailing space in line comments',
rules: { disallowTrailingWhitespace: true },
input: '// bla \n',
output: '// bla\n'
});

reportAndFix({
name: 'should fix trailing space in block comments',
rules: { disallowTrailingWhitespace: true },
input: '/*\nbla\n\t\n*/',
output: '/*\nbla\n\n*/'
});

reportAndFix({
name: 'should ignore empty lines',
rules: { disallowTrailingWhitespace: 'ignoreEmptyLines' },
input: 'var x; \n\t\n',
output: 'var x;\n\t\n'
});

reportAndFix({
name: 'should ignore empty lines in block comments',
rules: { disallowTrailingWhitespace: 'ignoreEmptyLines' },
input: '/* \nbla\n\t\n*/',
output: '/*\nbla\n\t\n*/'
});
});