Skip to content

Commit

Permalink
Fix: no-mixed-spaces-and-tabs reports multiline strings (#12566)
Browse files Browse the repository at this point in the history
* Fix: no-mixed-spaces-and-tabs reports multiline strings

* Add more tests for comments
  • Loading branch information
mdjermanovic authored and kaicataldo committed Dec 23, 2019
1 parent 8f1020f commit 1aff21b
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 66 deletions.
83 changes: 17 additions & 66 deletions lib/rules/no-mixed-spaces-and-tabs.js
Expand Up @@ -30,7 +30,6 @@ module.exports = {
const sourceCode = context.getSourceCode();

let smartTabs;
const ignoredLocs = [];

switch (context.options[0]) {
case true: // Support old syntax, maybe add deprecation warning here
Expand All @@ -41,72 +40,30 @@ module.exports = {
smartTabs = false;
}

/**
* Determines if a given line and column are before a location.
* @param {Location} loc The location object from an AST node.
* @param {int} line The line to check.
* @param {int} column The column to check.
* @returns {boolean} True if the line and column are before the location, false if not.
* @private
*/
function beforeLoc(loc, line, column) {
if (line < loc.start.line) {
return true;
}
return line === loc.start.line && column < loc.start.column;
}

/**
* Determines if a given line and column are after a location.
* @param {Location} loc The location object from an AST node.
* @param {int} line The line to check.
* @param {int} column The column to check.
* @returns {boolean} True if the line and column are after the location, false if not.
* @private
*/
function afterLoc(loc, line, column) {
if (line > loc.end.line) {
return true;
}
return line === loc.end.line && column > loc.end.column;
}

//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------

return {

TemplateElement(node) {
ignoredLocs.push(node.loc);
},

"Program:exit"(node) {
const lines = sourceCode.lines,
comments = sourceCode.getAllComments(),
ignoredCommentLines = new Set();

// Add all lines except the first ones.
comments.forEach(comment => {
for (let i = comment.loc.start.line + 1; i <= comment.loc.end.line; i++) {
ignoredCommentLines.add(i);
}
});

/*
* At least one space followed by a tab
* or the reverse before non-tab/-space
* characters begin.
*/
let regex = /^(?=[\t ]*(\t | \t))/u;
const lines = sourceCode.lines,
comments = sourceCode.getAllComments();

comments.forEach(comment => {
ignoredLocs.push(comment.loc);
});

ignoredLocs.sort((first, second) => {
if (beforeLoc(first, second.start.line, second.start.column)) {
return 1;
}

if (beforeLoc(second, first.start.line, second.start.column)) {
return -1;
}

return 0;
});

if (smartTabs) {

Expand All @@ -122,25 +79,19 @@ module.exports = {

if (match) {
const lineNumber = i + 1,
column = match.index + 1;
column = match.index + 1,
loc = { line: lineNumber, column };

for (let j = 0; j < ignoredLocs.length; j++) {
if (beforeLoc(ignoredLocs[j], lineNumber, column)) {
continue;
}
if (afterLoc(ignoredLocs[j], lineNumber, column)) {
continue;
}
if (!ignoredCommentLines.has(lineNumber)) {
const containingNode = sourceCode.getNodeByRangeIndex(sourceCode.getIndexFromLoc(loc));

return;
if (!(containingNode && ["Literal", "TemplateElement"].includes(containingNode.type))) {
context.report({ node, loc, message: "Mixed spaces and tabs." });
}
}

context.report({ node, loc: { line: lineNumber, column }, message: "Mixed spaces and tabs." });
}
});
}

};

}
};
78 changes: 78 additions & 0 deletions tests/lib/rules/no-mixed-spaces-and-tabs.js
Expand Up @@ -25,6 +25,12 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, {
"\t/*\n\t * Hello\n\t */",
"// foo\n\t/**\n\t * Hello\n\t */",
"/*\n\n \t \n*/",
"/*\t */ //",
"/*\n \t*/ //",
"/*\n\t *//*\n \t*/",
"// \t",
"/*\n*/\t ",
"/* \t\n\t \n \t\n\t */ \t",
{
code: "\tvar x = 5,\n\t y = 2;",
options: [true]
Expand Down Expand Up @@ -69,6 +75,8 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, {
code: "`foo${ 5 }\t `;",
env: { es6: true }
},
"' \t\\\n\t multiline string';",
"'\t \\\n \tmultiline string';",
{
code: "\tvar x = 5,\n\t y = 2;",
options: ["smart-tabs"]
Expand Down Expand Up @@ -96,6 +104,56 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, {
}
]
},
{
code: " \t/* comment */",
errors: [
{
message: "Mixed spaces and tabs.",
type: "Program",
line: 1
}
]
},
{
code: "\t // comment",
errors: [
{
message: "Mixed spaces and tabs.",
type: "Program",
line: 1
}
]
},
{
code: "\t var a /* comment */ = 1;",
errors: [
{
message: "Mixed spaces and tabs.",
type: "Program",
line: 1
}
]
},
{
code: " \tvar b = 1; // comment",
errors: [
{
message: "Mixed spaces and tabs.",
type: "Program",
line: 1
}
]
},
{
code: "/**/\n \t/*\n \t*/",
errors: [
{
message: "Mixed spaces and tabs.",
type: "Program",
line: 2
}
]
},
{
code: "\t var x = 5, y = 2, z = 5;\n\n\t \tvar j =\t x + y;\nz *= j;",
errors: [
Expand Down Expand Up @@ -157,6 +215,26 @@ ruleTester.run("no-mixed-spaces-and-tabs", rule, {
column: 2
}
]
},
{
code: " \t'';",
errors: [
{
message: "Mixed spaces and tabs.",
type: "Program",
line: 1
}
]
},
{
code: "''\n\t ",
errors: [
{
message: "Mixed spaces and tabs.",
type: "Program",
line: 2
}
]
}
]
});

0 comments on commit 1aff21b

Please sign in to comment.