JAVASCRIPT   50

no-regex-spaces.js

Guest on 21st August 2021 09:28:19 AM

  1. /**
  2.  * @fileoverview Rule to count multiple spaces in regular expressions
  3.  * @author Matt DuVall <http://www.mattduvall.com/>
  4.  */
  5.  
  6. "use strict";
  7.  
  8. const astUtils = require("../ast-utils");
  9.  
  10. //------------------------------------------------------------------------------
  11. // Rule Definition
  12. //------------------------------------------------------------------------------
  13.  
  14. module.exports = {
  15.     meta: {
  16.         docs: {
  17.             description: "disallow multiple spaces in regular expressions",
  18.             category: "Possible Errors",
  19.             recommended: true
  20.         },
  21.  
  22.         schema: [],
  23.  
  24.         fixable: "code"
  25.     },
  26.  
  27.     create(context) {
  28.         const sourceCode = context.getSourceCode();
  29.  
  30.         /**
  31.          * Validate regular expressions
  32.          * @param {ASTNode} node node to validate
  33.          * @param {string} value regular expression to validate
  34.          * @param {number} valueStart The start location of the regex/string literal. It will always be the case that
  35.          `sourceCode.getText().slice(valueStart, valueStart + value.length) === value`
  36.          * @returns {void}
  37.          * @private
  38.          */
  39.         function checkRegex(node, value, valueStart) {
  40.             const multipleSpacesRegex = /( {2,})+?/,
  41.                 regexResults = multipleSpacesRegex.exec(value);
  42.  
  43.             if (regexResults !== null) {
  44.                 const count = regexResults[0].length;
  45.  
  46.                 context.report({
  47.                     node,
  48.                     message: "Spaces are hard to count. Use {{{count}}}.",
  49.                     data: { count },
  50.                     fix(fixer) {
  51.                         return fixer.replaceTextRange(
  52.                             [valueStart + regexResults.index, valueStart + regexResults.index + count],
  53.                             ` {${count}}`
  54.                         );
  55.                     }
  56.                 });
  57.  
  58.                 /*
  59.                  * TODO: (platinumazure) Fix message to use rule message
  60.                  * substitution when api.report is fixed in lib/eslint.js.
  61.                  */
  62.             }
  63.         }
  64.  
  65.         /**
  66.          * Validate regular expression literals
  67.          * @param {ASTNode} node node to validate
  68.          * @returns {void}
  69.          * @private
  70.          */
  71.         function checkLiteral(node) {
  72.             const token = sourceCode.getFirstToken(node),
  73.                 nodeType = token.type,
  74.                 nodeValue = token.value;
  75.  
  76.             if (nodeType === "RegularExpression") {
  77.                 checkRegex(node, nodeValue, token.start);
  78.             }
  79.         }
  80.  
  81.         /**
  82.          * Check if node is a string
  83.          * @param {ASTNode} node node to evaluate
  84.          * @returns {boolean} True if its a string
  85.          * @private
  86.          */
  87.         function isString(node) {
  88.             return node && node.type === "Literal" && typeof node.value === "string";
  89.         }
  90.  
  91.         /**
  92.          * Validate strings passed to the RegExp constructor
  93.          * @param {ASTNode} node node to validate
  94.          * @returns {void}
  95.          * @private
  96.          */
  97.         function checkFunction(node) {
  98.             const scope = context.getScope();
  99.             const regExpVar = astUtils.getVariableByName(scope, "RegExp");
  100.             const shadowed = regExpVar && regExpVar.defs.length > 0;
  101.  
  102.             if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(node.arguments[0]) && !shadowed) {
  103.                 checkRegex(node, node.arguments[0].value, node.arguments[0].start + 1);
  104.             }
  105.         }
  106.  
  107.         return {
  108.             Literal: checkLiteral,
  109.             CallExpression: checkFunction,
  110.             NewExpression: checkFunction
  111.         };
  112.  
  113.     }
  114. };

Raw Paste


Login or Register to edit or fork this paste. It's free.