Skip to content

Commit

Permalink
Update: add fixer for no-regex-spaces (#7113)
Browse files Browse the repository at this point in the history
  • Loading branch information
not-an-aardvark authored and nzakas committed Sep 14, 2016
1 parent cc80467 commit b39ac2c
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 8 deletions.
2 changes: 2 additions & 0 deletions docs/rules/no-regex-spaces.md
@@ -1,5 +1,7 @@
# disallow multiple spaces in regular expression literals (no-regex-spaces)

(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#fix) automatically fixes problems reported by this rule.

Regular expressions can be very complex and difficult to understand, which is why it's important to keep them as simple as possible in order to avoid mistakes. One of the more error-prone things you can do with a regular expression is to use more than one space, such as:

```js
Expand Down
30 changes: 23 additions & 7 deletions lib/rules/no-regex-spaces.js
Expand Up @@ -5,6 +5,8 @@

"use strict";

const astUtils = require("../ast-utils");

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
Expand All @@ -17,7 +19,9 @@ module.exports = {
recommended: true
},

schema: []
schema: [],

fixable: "code"
},

create(context) {
Expand All @@ -27,19 +31,27 @@ module.exports = {
* Validate regular expressions
* @param {ASTNode} node node to validate
* @param {string} value regular expression to validate
* @param {number} valueStart The start location of the regex/string literal. It will always be the case that
`sourceCode.getText().slice(valueStart, valueStart + value.length) === value`
* @returns {void}
* @private
*/
function checkRegex(node, value) {
function checkRegex(node, value, valueStart) {
const multipleSpacesRegex = /( {2,})+?/,
regexResults = multipleSpacesRegex.exec(value);

if (regexResults !== null) {
const count = regexResults[0].length;

context.report({
node,
message: "Spaces are hard to count. Use {{{count}}}.",
data: {
count: regexResults[0].length
data: {count},
fix(fixer) {
return fixer.replaceTextRange(
[valueStart + regexResults.index, valueStart + regexResults.index + count],
` {${count}}`
);
}
});

Expand All @@ -62,7 +74,7 @@ module.exports = {
nodeValue = token.value;

if (nodeType === "RegularExpression") {
checkRegex(node, nodeValue);
checkRegex(node, nodeValue, token.start);
}
}

Expand All @@ -83,8 +95,12 @@ module.exports = {
* @private
*/
function checkFunction(node) {
if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(node.arguments[0])) {
checkRegex(node, node.arguments[0].value);
const scope = context.getScope();
const regExpVar = astUtils.getVariableByName(scope, "RegExp");
const shadowed = regExpVar && regExpVar.defs.length > 0;

if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(node.arguments[0]) && !shadowed) {
checkRegex(node, node.arguments[0].value, node.arguments[0].start + 1);
}
}

Expand Down
20 changes: 19 additions & 1 deletion tests/lib/rules/no-regex-spaces.js
Expand Up @@ -21,12 +21,15 @@ ruleTester.run("no-regex-spaces", rule, {
"var foo = new RegExp('bar {3}baz')",
"var foo = /bar\t\t\tbaz/;",
"var foo = RegExp('bar\t\t\tbaz');",
"var foo = new RegExp('bar\t\t\tbaz');"
"var foo = new RegExp('bar\t\t\tbaz');",
"var RegExp = function() {}; var foo = new RegExp('bar baz');",
"var RegExp = function() {}; var foo = RegExp('bar baz');"
],

invalid: [
{
code: "var foo = /bar baz/;",
output: "var foo = /bar {4}baz/;",
errors: [
{
message: "Spaces are hard to count. Use {4}.",
Expand All @@ -36,6 +39,7 @@ ruleTester.run("no-regex-spaces", rule, {
},
{
code: "var foo = RegExp('bar baz');",
output: "var foo = RegExp('bar {4}baz');",
errors: [
{
message: "Spaces are hard to count. Use {4}.",
Expand All @@ -45,12 +49,26 @@ ruleTester.run("no-regex-spaces", rule, {
},
{
code: "var foo = new RegExp('bar baz');",
output: "var foo = new RegExp('bar {4}baz');",
errors: [
{
message: "Spaces are hard to count. Use {4}.",
type: "NewExpression"
}
]
},
{

// `RegExp` is not shadowed in the scope where it's called
code: "{ let RegExp = function() {}; } var foo = RegExp('bar baz');",
output: "{ let RegExp = function() {}; } var foo = RegExp('bar {4}baz');",
parserOptions: {ecmaVersion: 6},
errors: [
{
message: "Spaces are hard to count. Use {4}.",
type: "CallExpression"
}
]
}
]
});

0 comments on commit b39ac2c

Please sign in to comment.