Giter Site home page Giter Site logo

ota-meshi / eslint-plugin-regexp Goto Github PK

View Code? Open in Web Editor NEW
394.0 7.0 9.0 4.68 MB

ESLint plugin for finding regex mistakes and style guide violations.

Home Page: https://ota-meshi.github.io/eslint-plugin-regexp/

License: MIT License

JavaScript 0.63% TypeScript 99.37%
eslint-plugin eslintplugin regexp regex regular-expression

eslint-plugin-regexp's Introduction

Introduction

eslint-plugin-regexp is ESLint plugin for finding RegExp mistakes and RegExp style guide violations.

NPM license NPM version NPM downloads NPM downloads NPM downloads NPM downloads NPM downloads Build Status Coverage Status

πŸ“› Features

This ESLint plugin provides linting rules relate to better ways to help you avoid problems when using RegExp.

  • Find the wrong usage of regular expressions, and their hints.
  • Enforces a consistent style of regular expressions.
  • Find hints for writing optimized regular expressions.
  • 80 plugin rules for regular expression syntax and features.

You can check on the Online DEMO.

πŸ“– Documentation

See documents.

πŸ’Ώ Installation

npm install --save-dev eslint eslint-plugin-regexp

Requirements

  • ESLint v8.44.0 and above
  • Node.js v18.x, v20.x and above

πŸ“– Usage

Add regexp to the plugins section of your eslint.config.js or .eslintrc configuration file (you can omit the eslint-plugin- prefix) and either use one of the two configurations available (recommended or all) or configure the rules you want:

The recommended configuration (New Config)

The plugin.configs["flat/recommended"] config enables a subset of the rules that should be most useful to most users. See lib/configs/rules/recommended.ts for more details.

// eslint.config.js
import * as regexpPlugin from "eslint-plugin-regexp"

export default [
    regexpPlugin.configs["flat/recommended"],
];

The recommended configuration (Legacy Config)

The plugin:regexp/recommended config enables a subset of the rules that should be most useful to most users. See lib/configs/rules/recommended.ts for more details.

// .eslintrc.js
module.exports = {
    "plugins": [
        "regexp"
    ],
    "extends": [
         // add more generic rulesets here, such as:
         // 'eslint:recommended',
        "plugin:regexp/recommended"
    ]
}

Advanced Configuration

Override/add specific rules configurations. See also: http://eslint.org/docs/user-guide/configuring.

// eslint.config.js
import * as regexpPlugin from "eslint-plugin-regexp"

export default [
    {
        plugins: { regexp: regexpPlugin }
        rules: {
            // Override/add rules settings here, such as:
            "regexp/rule-name": "error"
        }
    }
];
// .eslintrc.js
module.exports = {
    "plugins": [
        "regexp"
    ],
    "rules": {
        // Override/add rules settings here, such as:
        "regexp/rule-name": "error"
    }
}

Using the all configuration

The plugin.configs["flat/all"] / plugin:regexp/all config enables all rules. It's meant for testing, not for production use because it changes with every minor and major version of the plugin. Use it at your own risk. See lib/configs/rules/all.ts for more details.

βœ… Rules

πŸ’Ό Configurations enabled in.
⚠️ Configurations set to warn in.
🟒 Set in the flat/recommended configuration.
πŸ”΅ Set in the recommended configuration.
πŸ”§ Automatically fixable by the --fix CLI option.
πŸ’‘ Manually fixable by editor suggestions.

Possible Errors

NameΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β  Description πŸ’Ό ⚠️ πŸ”§ πŸ’‘
no-contradiction-with-assertion disallow elements that contradict assertions 🟒 πŸ”΅ πŸ’‘
no-control-character disallow control characters πŸ’‘
no-dupe-disjunctions disallow duplicate disjunctions 🟒 πŸ”΅ πŸ’‘
no-empty-alternative disallow alternatives without elements 🟒 πŸ”΅ πŸ’‘
no-empty-capturing-group disallow capturing group that captures empty. 🟒 πŸ”΅
no-empty-character-class disallow character classes that match no characters 🟒 πŸ”΅
no-empty-group disallow empty group 🟒 πŸ”΅
no-empty-lookarounds-assertion disallow empty lookahead assertion or empty lookbehind assertion 🟒 πŸ”΅
no-escape-backspace disallow escape backspace ([\b]) 🟒 πŸ”΅ πŸ’‘
no-invalid-regexp disallow invalid regular expression strings in RegExp constructors 🟒 πŸ”΅
no-lazy-ends disallow lazy quantifiers at the end of an expression 🟒 πŸ”΅ πŸ’‘
no-misleading-capturing-group disallow capturing groups that do not behave as one would expect 🟒 πŸ”΅ πŸ’‘
no-misleading-unicode-character disallow multi-code-point characters in character classes and quantifiers 🟒 πŸ”΅ πŸ”§ πŸ’‘
no-missing-g-flag disallow missing g flag in patterns used in String#matchAll and String#replaceAll 🟒 πŸ”΅ πŸ”§
no-optional-assertion disallow optional assertions 🟒 πŸ”΅
no-potentially-useless-backreference disallow backreferences that reference a group that might not be matched 🟒 πŸ”΅
no-super-linear-backtracking disallow exponential and polynomial backtracking 🟒 πŸ”΅ πŸ”§
no-super-linear-move disallow quantifiers that cause quadratic moves
no-useless-assertions disallow assertions that are known to always accept (or reject) 🟒 πŸ”΅ πŸ’‘
no-useless-backreference disallow useless backreferences in regular expressions 🟒 πŸ”΅
no-useless-dollar-replacements disallow useless $ replacements in replacement string 🟒 πŸ”΅
strict disallow not strictly valid regular expressions 🟒 πŸ”΅ πŸ”§ πŸ’‘

Best Practices

NameΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β  Description πŸ’Ό ⚠️ πŸ”§ πŸ’‘
confusing-quantifier disallow confusing quantifiers 🟒 πŸ”΅
control-character-escape enforce consistent escaping of control characters 🟒 πŸ”΅ πŸ”§
negation enforce use of escapes on negation 🟒 πŸ”΅ πŸ”§
no-dupe-characters-character-class disallow duplicate characters in the RegExp character class 🟒 πŸ”΅ πŸ”§
no-empty-string-literal disallow empty string literals in character classes 🟒 πŸ”΅
no-extra-lookaround-assertions disallow unnecessary nested lookaround assertions 🟒 πŸ”΅ πŸ”§
no-invisible-character disallow invisible raw character 🟒 πŸ”΅ πŸ”§
no-legacy-features disallow legacy RegExp features 🟒 πŸ”΅
no-non-standard-flag disallow non-standard flags 🟒 πŸ”΅
no-obscure-range disallow obscure character ranges 🟒 πŸ”΅
no-octal disallow octal escape sequence πŸ’‘
no-standalone-backslash disallow standalone backslashes (\)
no-trivially-nested-assertion disallow trivially nested assertions 🟒 πŸ”΅ πŸ”§
no-trivially-nested-quantifier disallow nested quantifiers that can be rewritten as one quantifier 🟒 πŸ”΅ πŸ”§
no-unused-capturing-group disallow unused capturing group 🟒 πŸ”΅ πŸ”§ πŸ’‘
no-useless-character-class disallow character class with one character 🟒 πŸ”΅ πŸ”§
no-useless-flag disallow unnecessary regex flags 🟒 πŸ”΅ πŸ”§
no-useless-lazy disallow unnecessarily non-greedy quantifiers 🟒 πŸ”΅ πŸ”§
no-useless-quantifier disallow quantifiers that can be removed 🟒 πŸ”΅ πŸ”§ πŸ’‘
no-useless-range disallow unnecessary character ranges 🟒 πŸ”΅ πŸ”§
no-useless-set-operand disallow unnecessary elements in expression character classes 🟒 πŸ”΅ πŸ”§
no-useless-string-literal disallow string disjunction of single characters in \q{...} 🟒 πŸ”΅ πŸ”§
no-useless-two-nums-quantifier disallow unnecessary {n,m} quantifier 🟒 πŸ”΅ πŸ”§
no-zero-quantifier disallow quantifiers with a maximum of zero 🟒 πŸ”΅ πŸ’‘
optimal-lookaround-quantifier disallow the alternatives of lookarounds that end with a non-constant quantifier 🟒 πŸ”΅ πŸ’‘
optimal-quantifier-concatenation require optimal quantifiers for concatenated quantifiers 🟒 πŸ”΅ πŸ”§
prefer-escape-replacement-dollar-char enforces escape of replacement $ character ($$).
prefer-predefined-assertion prefer predefined assertion over equivalent lookarounds 🟒 πŸ”΅ πŸ”§
prefer-quantifier enforce using quantifier πŸ”§
prefer-range enforce using character class range 🟒 πŸ”΅ πŸ”§
prefer-regexp-exec enforce that RegExp#exec is used instead of String#match if no global flag is provided
prefer-regexp-test enforce that RegExp#test is used instead of String#match and RegExp#exec πŸ”§
prefer-set-operation prefer character class set operations instead of lookarounds 🟒 πŸ”΅ πŸ”§
require-unicode-regexp enforce the use of the u flag πŸ”§
require-unicode-sets-regexp enforce the use of the v flag πŸ”§
simplify-set-operations require simplify set operations 🟒 πŸ”΅ πŸ”§
sort-alternatives sort alternatives if order doesn't matter πŸ”§
use-ignore-case use the i flag if it simplifies the pattern 🟒 πŸ”΅ πŸ”§

Stylistic Issues

NameΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β  Description πŸ’Ό ⚠️ πŸ”§ πŸ’‘
grapheme-string-literal enforce single grapheme in string literal
hexadecimal-escape enforce consistent usage of hexadecimal escape πŸ”§
letter-case enforce into your favorite case πŸ”§
match-any enforce match any character style 🟒 πŸ”΅ πŸ”§
no-useless-escape disallow unnecessary escape characters in RegExp 🟒 πŸ”΅ πŸ”§
no-useless-non-capturing-group disallow unnecessary non-capturing group 🟒 πŸ”΅ πŸ”§
prefer-character-class enforce using character class 🟒 πŸ”΅ πŸ”§
prefer-d enforce using \d 🟒 πŸ”΅ πŸ”§
prefer-lookaround prefer lookarounds over capturing group that do not replace πŸ”§
prefer-named-backreference enforce using named backreferences πŸ”§
prefer-named-capture-group enforce using named capture groups
prefer-named-replacement enforce using named replacement πŸ”§
prefer-plus-quantifier enforce using + quantifier 🟒 πŸ”΅ πŸ”§
prefer-question-quantifier enforce using ? quantifier 🟒 πŸ”΅ πŸ”§
prefer-result-array-groups enforce using result array groups πŸ”§
prefer-star-quantifier enforce using * quantifier 🟒 πŸ”΅ πŸ”§
prefer-unicode-codepoint-escapes enforce use of unicode codepoint escapes 🟒 πŸ”΅ πŸ”§
prefer-w enforce using \w 🟒 πŸ”΅ πŸ”§
sort-character-class-elements enforces elements order in character class πŸ”§
sort-flags require regex flags to be sorted 🟒 πŸ”΅ πŸ”§
unicode-escape enforce consistent usage of unicode escape or unicode codepoint escape πŸ”§
unicode-property enforce consistent naming of unicode properties πŸ”§

Removed

  • β›” These rules have been removed in a previous major release, after they have been deprecated for a while.
Rule ID Replaced by Removed in version
no-assertion-capturing-group regexp/no-empty-capturing-group v2.0.0
no-useless-exactly-quantifier regexp/no-useless-quantifier, regexp/no-zero-quantifier v2.0.0
no-useless-non-greedy regexp/no-useless-lazy v2.0.0
order-in-character-class regexp/sort-character-class-elements v2.0.0
prefer-t regexp/control-character-escape v2.0.0

βš™οΈ Settings

See Settings.

πŸš₯ Semantic Versioning Policy

eslint-plugin-regexp follows Semantic Versioning and ESLint's Semantic Versioning Policy.

🍻 Contributing

Welcome contributing!

Please use GitHub's Issues/PRs.

See CONTRIBUTING.md.

Development Tools

  • npm test runs tests and measures coverage.
  • npm run update runs in order to update readme and recommended configuration.
  • npm run new [new rule name] runs to create the files needed for the new rule.
  • npm run docs:watch starts the website locally.

πŸ”’ License

See the LICENSE file for license rights and limitations (MIT).

eslint-plugin-regexp's People

Contributors

bmish avatar darkred avatar dependabot[bot] avatar eugeno avatar github-actions[bot] avatar kevinoid avatar logicer16 avatar ota-meshi avatar regseb avatar renovate-bot avatar renovate[bot] avatar rundevelopment avatar slapbox avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

eslint-plugin-regexp's Issues

New rule to forbid literal backslashes

In non-Unicode mode, the regex /\c/ is equivalent to /\\c/. The \ in /\c/ is a literal backslash. It would probably be good to have a rule that detects this rather strange behavior.

Rule proposal: Forbid range `Z-a`

New users may use /[A-f]/, to match [A-Za-f] or [A-Fa-F], but it's neither, there are other strings in this range, they just don't know.

/[A-f]/.test('[')
true

Fail

/[A-z]/

Any range include Z-a

Pass

/[A-Za-z]/

Suggest `i` flag if it simplifies the pattern

If a pattern can be simplified by adding the i flag (e.g. /[a-fA-F]/ -> /[a-f]/i), it might be a good idea to suggest that to the user.

The conditions for this rule to add the i flag (and subsequently simplify the pattern) are:

  1. The i flag isn't present.
  2. All characters, character classes, and character sets match the same character(s) regardless of the i flag (aka. the flag doesn't change the meaning of the pattern.)
  3. There is at least one character class that can be simplified because of the added i flag. E.g. a character range can be removed, or a character class can be replaced by a character or character set, or similar.

Categorize rules

The list of supported rules is getting long (56 rules) and will only get longer in the future.

I think we should categorize our rules so our users can quickly find rules with somewhat similar functionality.

For now, I think the categories "Possible Errors", "Best Practices", and "Stylistic Issues" (taken from the ESLint website) might be a good fit.

@ota-meshi What do you think about this?

Sort word lists rule

Some regexes contain (potentially long) lists of words. E.g. almost every language over at Prism has at least one regex like this.

For many of those lists, the order of alternatives doesn't matter. I.e. most word lists in Prism are surrounded with \bs. In this case, we are free to reorder (=sort) the alternatives.

Sorting these lists is beneficial because it makes it easier for humans to find words. This makes it easier to maintain the regexes containing these lists.

Another additional advantage is that compression algorithms (e.g. gzip) are typically able to better compress sorted lists. I tested this with a few examples and sorted lists were around 10% smaller when compressed with gzip.


This rule is basically order-in-character-class but for groups.

no-dupe-characters-character-class: Incompatible flags: The i flag is forbidden to create a literal but required by the options.

Hello, no-dupe-characters-character-class rule seems to crash in certain cases. This issue was spotted by automated CI run - it is not blocking my development or anything. https://github.com/AriPerkkio/eslint-remote-tester/actions/runs/795820693

"eslint-plugin-regexp": "^0.9.0",
{
  "root": true,
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": 2020,
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx": true
    }
  },
  "plugins": ["regexp"],
  "rules": {
    "regexp/no-dupe-characters-character-class": "error"
  }
}

Minimal repro:

new RegExp(`[^\\w\\s\u00C0-\u00F6\u00F8-\u017E]`, "gi");
Error: Incompatible flags: The i flag is forbidden to create a literal but required by the options.
Occurred while linting <text>:1
    at fl (/home/<removed>/eslint-remote-tester/ci/node_modules/refa/index.js:1:715985)
    at Object.toLiteral (/home/<removed>/eslint-remote-tester/ci/node_modules/refa/index.js:1:733343)
    at Object.toCharSetSource (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:487:22)

Crash reports from real projects

Rule: no-dupe-characters-character-class

  • Message: Incompatible flags: The i flag is forbidden to create a literal but required by the options. Occurred while linting <text>:72
  • Path: aws/aws-northstar/src/components/FormRenderer/index.stories.tsx
  • Link
  70 |                     type: validatorTypes.PATTERN,
  71 |                     message: 'Invalid email address',
> 72 |                     pattern: /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/i,
  73 |                 },
  74 |             ],
  75 |         },
Error: Incompatible flags: The i flag is forbidden to create a literal but required by the options.
Occurred while linting <text>:72
    at fl (/home/<removed>/eslint-remote-tester/ci/node_modules/refa/index.js:1:715985)
    at Object.toLiteral (/home/<removed>/eslint-remote-tester/ci/node_modules/refa/index.js:1:733343)
    at Object.toCharSetSource (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:487:22)
    at reportIntersect (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/rules/no-dupe-characters-character-class.js:89:47)
    at onCharacterClassEnter (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/rules/no-dupe-characters-character-class.js:177:37)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:105:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)

Rule: no-dupe-characters-character-class

  • Message: Incompatible flags: The i flag is forbidden to create a literal but required by the options. Occurred while linting <text>:1
  • Path: IBMStreams/vscode-ide/src/webviews/cloudPakForDataJob/resources/utils.js
  • Link
> 1 | const JOB_NAME_MAX_LENGTH = 100;
  2 | const JOB_DESCRIPTION_MAX_LENGTH = 300;
  3 | const STREAMS_JOB_NAME_MAX_LENGTH = 1024;
  4 | const STREAMS_JOB_NAME_REGEX = new RegExp(
Error: Incompatible flags: The i flag is forbidden to create a literal but required by the options.
Occurred while linting <text>:1
    at fl (/home/<removed>/eslint-remote-tester/ci/node_modules/refa/index.js:1:715985)
    at Object.toLiteral (/home/<removed>/eslint-remote-tester/ci/node_modules/refa/index.js:1:733343)
    at Object.toCharSetSource (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:487:22)
    at reportIntersect (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/rules/no-dupe-characters-character-class.js:89:47)
    at onCharacterClassEnter (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/rules/no-dupe-characters-character-class.js:177:37)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:105:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)

Rule: no-dupe-characters-character-class

  • Message: Incompatible flags: The i flag is forbidden to create a literal but required by the options. Occurred while linting <text>:2
  • Path: kmjennison/react-sparkle/docs/component---src-pages-index-js-1209acb7120be946afae.js
  • Link
  1 | /*! For license information please see component---src-pages-index-js-1209acb7120be946afae.js.LICENSE.txt */
> 2 | (window.webpackJsonp=window.webpackJsonp||[]).push([[3],{"++L3":function(e,t,n){"...
  3 | //# sourceMappingURL=component---src-pages-index-js-1209acb7120be946afae.js.map
Error: Incompatible flags: The i flag is forbidden to create a literal but required by the options.
Occurred while linting <text>:2
    at fl (/home/<removed>/eslint-remote-tester/ci/node_modules/refa/index.js:1:715985)
    at Object.toLiteral (/home/<removed>/eslint-remote-tester/ci/node_modules/refa/index.js:1:733343)
    at Object.toCharSetSource (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:487:22)
    at reportIntersect (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/rules/no-dupe-characters-character-class.js:89:47)
    at onCharacterClassEnter (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/rules/no-dupe-characters-character-class.js:177:37)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:105:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)

Rule: no-dupe-characters-character-class

  • Message: Incompatible flags: The i flag is forbidden to create a literal but required by the options. Occurred while linting <text>:2
  • Path: kmjennison/react-sparkle/docs/component---src-pages-index-js-1d4c46f63ded03d7f5e1.js
  • Link
  1 | /*! For license information please see component---src-pages-index-js-1d4c46f63ded03d7f5e1.js.LICENSE.txt */
> 2 | (window.webpackJsonp=window.webpackJsonp||[]).push([[3],{"++L3":function(e,t,n){"use strict";...
  3 | //# sourceMappingURL=component---src-pages-index-js-1d4c46f63ded03d7f5e1.js.map
Error: Incompatible flags: The i flag is forbidden to create a literal but required by the options.
Occurred while linting <text>:2
    at fl (/home/<removed>/eslint-remote-tester/ci/node_modules/refa/index.js:1:715985)
    at Object.toLiteral (/home/<removed>/eslint-remote-tester/ci/node_modules/refa/index.js:1:733343)
    at Object.toCharSetSource (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:487:22)
    at reportIntersect (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/rules/no-dupe-characters-character-class.js:89:47)
    at onCharacterClassEnter (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/rules/no-dupe-characters-character-class.js:177:37)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:105:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)

Rule: no-dupe-characters-character-class

  • Message: Incompatible flags: The i flag is forbidden to create a literal but required by the options. Occurred while linting <text>:2
  • Path: kmjennison/react-sparkle/docs/component---src-pages-index-js-fda99f169ba46368955c.js
  • Link
  1 | /*! For license information please see component---src-pages-index-js-fda99f169ba46368955c.js.LICENSE.txt */
> 2 | (window.webpackJsonp=window.webpackJsonp||[]).push([[3],{"++L3":function(e,t,n){"use strict";var a=n("VOTz"),r=n(...
  3 | //# sourceMappingURL=component---src-pages-index-js-fda99f169ba46368955c.js.map
Error: Incompatible flags: The i flag is forbidden to create a literal but required by the options.
Occurred while linting <text>:2
    at fl (/home/<removed>/eslint-remote-tester/ci/node_modules/refa/index.js:1:715985)
    at Object.toLiteral (/home/<removed>/eslint-remote-tester/ci/node_modules/refa/index.js:1:733343)
    at Object.toCharSetSource (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:487:22)
    at reportIntersect (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/rules/no-dupe-characters-character-class.js:89:47)
    at onCharacterClassEnter (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/rules/no-dupe-characters-character-class.js:177:37)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:105:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)
    at handler.<computed> (/home/<removed>/eslint-remote-tester/ci/node_modules/eslint-plugin-regexp/dist/utils/index.js:104:25)

Release v0.9.0

I plan to release the minor version about once every two weeks.
However, this plugin repository has already incorporated many changes since v0.8.0. v0.8.0...master
So it hasn't been long since the release of v0.8.0, but I would like to release v0.9.0.
@RunDevelopment Could you let me know if you think it's okay to release v0.9.0?

`getUsageOfPattern` behaves inconsistently

While writing tests, I found that getUsageOfPattern behaves strangely around unknown functions.

The following test cases pass.

{
    code: `foo(/[a-zA-Z]\\w*/)`,
    results: [UsageOfPattern.whole],
},
{
    code: `foo({ pattern: /[a-zA-Z]\\w*/ })`,
    results: [UsageOfPattern.unknown],
},

Both should have the same result: unknown. We do not know how foo is implemented. It might use the regex as is or it might return its source.

`no-dupe-characters-character-class` behaves strangely with `\s`

For the character class [\xA0-\uFFFF\s] (all spaces and non-ascii), I get the following error message:

Unexpected intersection of "\xA0-\uFFFF" and "\s" was found "\u00a0".

I find it a little strange that this gets reported as an error. Is this correct?

Assuming that it is, I can just skip \xA0 easily, so let's re-run the rule on /[\xA1-\uFFFF\s]/.

No Errors.

Now that is strange. \xA1-\uFFFF and \s aren't disjoint. They both share quite a few characters. Why doesn't \u1680 get reported as well?

Tooling should not emit Windows line breaks

The tooling scripts shouldn't create files with Windows line ends. CRLF just makes everything more complex:

  • We have to rely on Windows developers to have their git configured correctly to commit LF. (I luckily did)
  • We have to support reading CRLF line ends. This isn't the case right now. The tooling just breaks.

Would we even accept PRs that add files with CRLF line ends?

Consistent control escapes

As mentioned by @ota-meshi here:

[...] we may need another rule to convert it [\x0a] to \n.

I want to add that we could make a rule to consistently escape control characters.

We already have prefer-t which does exactly this for \t. We should probably deprecate prefer-t in favor of a more general rule that handles \t, \r, \n, and \f.

(The rule should also be aware of rules like no-obscure-range, so we don't have two rules fighting each other.)

`prefer-question-quantifier` ignores alternative order

The order of alternatives matters in JS regexp. The easiest example of this is that /a|aa/ != /aa|a/. This library even has a rule to detect this case but it will falsely automatically "fix" the regex /a(?:|a)/ to /a(?:a)?/. The problem here is that /a|aa/ == /a(?:|a)/ != /a(?:a)?/ == /a(?:a|)/ == /aa|a/.

`order-in-character-class`: Reported on references

const jsxWhitespaceChars = " \n\r\t";
const matchJsxWhitespaceRegex = new RegExp("([" + jsxWhitespaceChars + "]+)");
                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The problem is reported here

The location is miss leading, because there is no \n there.

Is it hard? I didn't read code, but I think strings are concated, lost original node info?

Another problem \n/\t/ should be escaped in message, they are invisible.

New rule to enforce consistent hex escape

Characters that can use hexadecimal escape can use both hexadecimal escape and unicode escape.
I think it useful to have a new rule that enforces the consistent use of hexadecimal escapes.

Rule Name: regexp/hexadecimal-escape
Options:

  • "always" ... Expects that the hexadecimal escape will be used whenever possible. This is default.
  • "never" ... Ensures that no hexadecimal escape is used in any characters.

`no-useless-range` fail to escape some characters

Here are some character classes that will be fixed incorrectly:

/[,--b]/ -> /[,-b]/
/[\c-d]/ -> /[\cd]/

These examples are very artificial but should be fixed at some point. This is a low-priority bug.

Detect super-linear worst-case runtime

I think we should add a rule that reports cases for exponential backtracking and polynomial backtracking.

However, there are two problems standing in our way:

Performance

Detecting exponential backtracking is computationally expensive.

Static analysis methods might only take a few milliseconds per regex but this will quickly add up for a large codebase (e.g. Prism has about 2k regexes). Fuzzers will usually take about one second or more per regex and are completely impractical for our purposes.

Solutions

  • Since the detection itself is deterministic, a simple cache might largely solve the performance problem.

    However, I am not aware of ESLint providing such a feature.

Detection

I am not aware of any existing detector implementation in JavaScript (time of writing: 2021-04-19).

safe-regex isn't practical. It implements a detection method that simply doesn't work. Star height has little to do with exponential runtime. I.e. (a|a)*b has a star height of 1 and the (a|a)* will cause exponential backtracking, and (ab+)*c has a star height of 2 without any form of exponential backtracking.

Solutions

  • Right now, we could use my library scslre to detect at least some polynomial and exponential backtracking quickly. scslre even offers fixes for simple cases.

  • There is also this method I implemented for Prism. This method is currently used in PrismJS and Highlight.JS. The upside of this method is that it is quick. It can analyze the >2.5k regexes of Prism in less than 5 seconds. The downside of this method is that there are false negatives and it cannot offer fixes. However, the positives it does find are mostly true positives.

    I should note that half of this method is already partially implemented by the no-dupe-disjunctions rule. If we find two alternatives that are not disjoint and both are children of a star quantifier, then we can reasonably assume that this will cause exponential backtracking (e.g. (a|a)*). Changing the no-dupe-disjunctions to add this information should be fairly easy.

  • Given that refa recently added ENFAs (not published yet), someone could probably implement a detection method like RXXR fairly easily.

  • I am currently writing my Bachelor thesis on a new static analysis method for exponential and polynomial backtracking. Part of this will be a JS library implementing my new detection method. We could also use this when it's ready (probably in 3-4 months or so).


Related:

`regexp/no-octal` allows some octal escapes

Why does regexp/no-octal allow octal escapes that do not start with a 0? These octal escapes are especially harmful because they look like backreferences.

In fact, whether \2 is an octal escape or a backreference depends on the number of capturing groups in the pattern. This is a big problem because this means that adding capturing groups might change some octal escapes into backreferences. Similarly, removing capturing group might leave backreferences that are now interpreted as octal escapes.

`regexp/prefer-range` and not obvious cases

Could you add an option to make this rule work only with obvious cases, but not with cases like those?

/[!'()~]|%20/g

Unexpected multiple adjacent characters. Use "'-)" instead

/^[\u0000-\u001F ]+|[\u0000-\u001F ]+$/g

Unexpected multiple adjacent characters. Use "\u0000- " instead

`regexp/negation` false positives because of `i` flag

See the following example:

var re2 = /[^\P{Ll}]/iu;

image

Ignoring the strange suggested fix (this will be a separate issue), the report is incorrect.

/[^\P{Ll}]/iu != /\p{Ll}/iu:
The Canonicalize operation of the i flag is applied before the character class is inverted. This example, \P{Ll} means "all character that are not lower-case letters". Since\p{Ll} contains all upper-case letters, it will also contain all lower-case letters after the Canonicalize operation (not quite right but almost), so \P{Ll} matches (almost) all characters. The character class will then match (almost) no character because it is inverted. This is obviously very different from /\p{Ll}/iu which matches (almost) all letter characters.

Suggestion: add an `all` configuration

Currently, the only configuration available is recommended (see).
The alternative the user has is to manually configure the rules he wants.

My suggestion is to offer an additional all configuration.

For reference, ESLint itself offers both recommended and all (see) configuration:

Notes from documentation:

Use "eslint:recommended" to enables a subset of core rules that report common problems.

Use "eslint:all" to enable all core rules in the currently installed version of ESLint. The set of core rules can change at any minor or major version of ESLint.

Important: This configuration is not recommended for production use because it changes with every minor and major version of ESLint. Use it at your own risk.

With the active development taking place for this plugin and the wide range of rules,
I believe it would be useful for the user to be able to try the all configuration on his project,
to see which more rules he would like to enable.

Rule proposal: Prefer lookahead and lookbehind

Avoid capture unneeded groups.

Fail

'I love unicorn! I hate unicorn?'.replace(/(?<before>love )unicorn(?<after>!)/, '$<before>πŸ¦„$<after>');
'I love unicorn! I hate unicorn?'.replace(/(love )unicorn(!)/, '$1πŸ¦„$2');

Pass

'I love unicorn! I hate unicorn?'.replace(/(?<=love )unicorn(?=!)/, 'πŸ¦„');

Original posted in sindresorhus/eslint-plugin-unicorn#1113, can we implement it here?

Added more Playground examples

We have so many good features but we don't show them to people. We should change that!

Add more examples to the playground. The examples should highlight cool rules/rule combinations and show how this plugin finds real issues.

Start website locally

Is there an easy way to start the website locally? There doesn't seem to be a script that does it.

It's also quite difficult to just start a local server because all paths in the website itself are prefixed with "/eslint-plugin-regexp/". Removing that prefix will cause Vue to generate different absolute paths. This enables me that start the website locally but it will break the live website.

`prefer-range` combines adjacent but not-allowed ranges.

With the settings:

settings: {
	regexp: {
		// allow alphanumeric and cyrillic ranges
		allowedCharacterRanges: ['alphanumeric', 'а-я', 'А-Я']
	}
},

prefer-range will combine [а-яА-Я] into [А-я] which then gets reported by no-obscure-range as an error. Clearly, perfer-range is a little too eager.

Improve `no-dupe-disjunctions` by reordering alternatives

To implement sort-alternatives, I had to implement a method to decide whether two alternatives can be reordered.

We can use this method to improve the reporting of no-dupe-disjunctions. Right now, superset alternatives are not reported by default (e.g. /\b(?:Foo|\w+)\b/). But if the alternatives can be reordered, a superset alternative can be become a subset alternative (e.g. /\b(?:Foo|\w+)\b/ == /\b(?:\w+|Foo)\b/).

Rule proposal: Forbid `g` flag used on `RegExp#test()`

If the regex is only used once on RegExp#test(), the g flag is useless.

Fail

/foo/g.test(bar);
new RegExp('foo', 'g').test(bar);

Pass

const regex = /foo/g;
regex.test(bar);

I original make this proposal here, but feel better put RegExp related rules together in this codebase.

`isCoveredNode` false positive

I found a false positive the isCoveredNodemethod produces.

  /(^|\s)[+-]?(?:\d*\.\d+|\d+\.\d*|\d+)(?:e[+-]?\d+)?(?=\s|$)/i
//               ^~~~~~~~ ^~~~~~~~
//                   ^       / 
//                    \_____/ is covered by

isCoveredNode thinks that \d+\.\d* (2nd alt) is covered by \d*\.\d+ (1st alt).

I found this bug because of a false positive the no-dupe-disjunction rule produced because of it.

New rule `prefer-named-backreferences`

Backreferences to named groups should probably refer to the group by name and not by number.

// valid
- /(a)\1/u
- /(?<foo>a)\k<foo>/u

// invalid
- /(?<foo>a)\1/u
//          ^~

The rule should be auto-fixable.

Useless `y` flag

I just learned that RegExp.prototype [ @@split ] automatically adds a y flag to the regexp. As noted:

The @@split method ignores the value of the "global" and "sticky" properties of this RegExp object.

This means that "str".split(/re/) and "str".split(/re/gy) are equivalent. The no-useless-flag rule current does report the g flag but not the y flag.

`no-useless-flag` needs better error messages

image

The 'g' flag is unnecessary because not using global testing.

The current error message doesn't really say anything. A better error message would be: "The 'g' flag is unnecessary because String.prototype.split ignores the 'g' flag." or something like that.

Same problem for other string methods and flags.

Also, now that I got the error message: What's "global testing" @ota-meshi?


I wound how we could fix this.

The current implementation seems to mark flags as used. Maybe we could keep a list of everything that uses the regex? If we know that the regex is used by exactly one method and that method doesn't use a flag, we can give a more specific error message. Would that work?

Add rules that "eslint-plugin-clean-regex" has

Check each rule that eslint-plugin-clean-regex has, add the missing rule, and if eslint-plugin-regexp already has a similar rule, check for missing validation is needed.
Also, if we keep a note of the rule correspondence, it may be a document when creating a migration tool.

If we want to discuss one rule, we can also open a new issue.

Problems

Suggestions

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.