| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 | 
							- /**
 
-  * @fileoverview Rule to count multiple spaces in regular expressions
 
-  * @author Matt DuVall <http://www.mattduvall.com/>
 
-  */
 
- "use strict";
 
- //------------------------------------------------------------------------------
 
- // Requirements
 
- //------------------------------------------------------------------------------
 
- const astUtils = require("./utils/ast-utils");
 
- const regexpp = require("regexpp");
 
- //------------------------------------------------------------------------------
 
- // Helpers
 
- //------------------------------------------------------------------------------
 
- const regExpParser = new regexpp.RegExpParser();
 
- const DOUBLE_SPACE = / {2}/u;
 
- /**
 
-  * 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";
 
- }
 
- //------------------------------------------------------------------------------
 
- // Rule Definition
 
- //------------------------------------------------------------------------------
 
- module.exports = {
 
-     meta: {
 
-         type: "suggestion",
 
-         docs: {
 
-             description: "disallow multiple spaces in regular expressions",
 
-             category: "Possible Errors",
 
-             recommended: true,
 
-             url: "https://eslint.org/docs/rules/no-regex-spaces"
 
-         },
 
-         schema: [],
 
-         fixable: "code",
 
-         messages: {
 
-             multipleSpaces: "Spaces are hard to count. Use {{{length}}}."
 
-         }
 
-     },
 
-     create(context) {
 
-         /**
 
-          * Validate regular expression
 
-          * @param {ASTNode} nodeToReport Node to report.
 
-          * @param {string} pattern Regular expression pattern to validate.
 
-          * @param {string} rawPattern Raw representation of the pattern in the source code.
 
-          * @param {number} rawPatternStartRange Start range of the pattern in the source code.
 
-          * @param {string} flags Regular expression flags.
 
-          * @returns {void}
 
-          * @private
 
-          */
 
-         function checkRegex(nodeToReport, pattern, rawPattern, rawPatternStartRange, flags) {
 
-             // Skip if there are no consecutive spaces in the source code, to avoid reporting e.g., RegExp(' \ ').
 
-             if (!DOUBLE_SPACE.test(rawPattern)) {
 
-                 return;
 
-             }
 
-             const characterClassNodes = [];
 
-             let regExpAST;
 
-             try {
 
-                 regExpAST = regExpParser.parsePattern(pattern, 0, pattern.length, flags.includes("u"));
 
-             } catch {
 
-                 // Ignore regular expressions with syntax errors
 
-                 return;
 
-             }
 
-             regexpp.visitRegExpAST(regExpAST, {
 
-                 onCharacterClassEnter(ccNode) {
 
-                     characterClassNodes.push(ccNode);
 
-                 }
 
-             });
 
-             const spacesPattern = /( {2,})(?: [+*{?]|[^+*{?]|$)/gu;
 
-             let match;
 
-             while ((match = spacesPattern.exec(pattern))) {
 
-                 const { 1: { length }, index } = match;
 
-                 // Report only consecutive spaces that are not in character classes.
 
-                 if (
 
-                     characterClassNodes.every(({ start, end }) => index < start || end <= index)
 
-                 ) {
 
-                     context.report({
 
-                         node: nodeToReport,
 
-                         messageId: "multipleSpaces",
 
-                         data: { length },
 
-                         fix(fixer) {
 
-                             if (pattern !== rawPattern) {
 
-                                 return null;
 
-                             }
 
-                             return fixer.replaceTextRange(
 
-                                 [rawPatternStartRange + index, rawPatternStartRange + index + length],
 
-                                 ` {${length}}`
 
-                             );
 
-                         }
 
-                     });
 
-                     // Report only the first occurrence of consecutive spaces
 
-                     return;
 
-                 }
 
-             }
 
-         }
 
-         /**
 
-          * Validate regular expression literals
 
-          * @param {ASTNode} node node to validate
 
-          * @returns {void}
 
-          * @private
 
-          */
 
-         function checkLiteral(node) {
 
-             if (node.regex) {
 
-                 const pattern = node.regex.pattern;
 
-                 const rawPattern = node.raw.slice(1, node.raw.lastIndexOf("/"));
 
-                 const rawPatternStartRange = node.range[0] + 1;
 
-                 const flags = node.regex.flags;
 
-                 checkRegex(
 
-                     node,
 
-                     pattern,
 
-                     rawPattern,
 
-                     rawPatternStartRange,
 
-                     flags
 
-                 );
 
-             }
 
-         }
 
-         /**
 
-          * 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;
 
-             const patternNode = node.arguments[0];
 
-             const flagsNode = node.arguments[1];
 
-             if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(patternNode) && !shadowed) {
 
-                 const pattern = patternNode.value;
 
-                 const rawPattern = patternNode.raw.slice(1, -1);
 
-                 const rawPatternStartRange = patternNode.range[0] + 1;
 
-                 const flags = isString(flagsNode) ? flagsNode.value : "";
 
-                 checkRegex(
 
-                     node,
 
-                     pattern,
 
-                     rawPattern,
 
-                     rawPatternStartRange,
 
-                     flags
 
-                 );
 
-             }
 
-         }
 
-         return {
 
-             Literal: checkLiteral,
 
-             CallExpression: checkFunction,
 
-             NewExpression: checkFunction
 
-         };
 
-     }
 
- };
 
 
  |