summaryrefslogtreecommitdiff
path: root/tools/node_modules/eslint/lib/rules/no-regex-spaces.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/node_modules/eslint/lib/rules/no-regex-spaces.js')
-rw-r--r--tools/node_modules/eslint/lib/rules/no-regex-spaces.js114
1 files changed, 114 insertions, 0 deletions
diff --git a/tools/node_modules/eslint/lib/rules/no-regex-spaces.js b/tools/node_modules/eslint/lib/rules/no-regex-spaces.js
new file mode 100644
index 0000000000..9250437caa
--- /dev/null
+++ b/tools/node_modules/eslint/lib/rules/no-regex-spaces.js
@@ -0,0 +1,114 @@
+/**
+ * @fileoverview Rule to count multiple spaces in regular expressions
+ * @author Matt DuVall <http://www.mattduvall.com/>
+ */
+
+"use strict";
+
+const astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "disallow multiple spaces in regular expressions",
+ category: "Possible Errors",
+ recommended: true
+ },
+
+ schema: [],
+
+ fixable: "code"
+ },
+
+ create(context) {
+ const sourceCode = context.getSourceCode();
+
+ /**
+ * 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, valueStart) {
+ const multipleSpacesRegex = /( {2,})( [+*{?]|[^+*{?]|$)/,
+ regexResults = multipleSpacesRegex.exec(value);
+
+ if (regexResults !== null) {
+ const count = regexResults[1].length;
+
+ context.report({
+ node,
+ message: "Spaces are hard to count. Use {{{count}}}.",
+ data: { count },
+ fix(fixer) {
+ return fixer.replaceTextRange(
+ [valueStart + regexResults.index, valueStart + regexResults.index + count],
+ ` {${count}}`
+ );
+ }
+ });
+
+ /*
+ * TODO: (platinumazure) Fix message to use rule message
+ * substitution when api.report is fixed in lib/eslint.js.
+ */
+ }
+ }
+
+ /**
+ * Validate regular expression literals
+ * @param {ASTNode} node node to validate
+ * @returns {void}
+ * @private
+ */
+ function checkLiteral(node) {
+ const token = sourceCode.getFirstToken(node),
+ nodeType = token.type,
+ nodeValue = token.value;
+
+ if (nodeType === "RegularExpression") {
+ checkRegex(node, nodeValue, token.range[0]);
+ }
+ }
+
+ /**
+ * Check if node is a string
+ * @param {ASTNode} node node to evaluate
+ * @returns {boolean} True if its a string
+ * @private
+ */
+ function isString(node) {
+ return node && node.type === "Literal" && typeof node.value === "string";
+ }
+
+ /**
+ * Validate strings passed to the RegExp constructor
+ * @param {ASTNode} node node to validate
+ * @returns {void}
+ * @private
+ */
+ function checkFunction(node) {
+ 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].range[0] + 1);
+ }
+ }
+
+ return {
+ Literal: checkLiteral,
+ CallExpression: checkFunction,
+ NewExpression: checkFunction
+ };
+
+ }
+};