Repository: ota-meshi/eslint-plugin-regexp (ts)

Issue:
`no-useless-flag` false positive for `i` flag and Unicode property escapes
See the following example:

```js
var re1 = /\p{Ll}/iu;
```

![image](https://user-images.githubusercontent.com/20878432/124462849-5bcc2000-dd92-11eb-88f2-28220ade0ef9.png)

This report is incorrect as `\p{Ll}` matches all lower-case letters. The `i` flag is very much necessary.

Pull request:
Fixed `toCharSet` ignoring optional flags
This fixes #265.

Patch:
diff --git a/.github/workflows/NodeCI.yml b/.github/workflows/NodeCI.yml
index ac07536..79a4e00 100644
--- a/.github/workflows/NodeCI.yml
+++ b/.github/workflows/NodeCI.yml
@@ -59,7 +59,7 @@ jobs:
             - name: Test
               run: npm run test:nyc
             - name: Coveralls GitHub Action
-              uses: coverallsapp/github-action@v1.1.2
+              uses: coverallsapp/github-action@1.1.3
               with:
                   github-token: ${{ secrets.GITHUB_TOKEN }}
     update:
diff --git a/lib/rules/negation.ts b/lib/rules/negation.ts
index 2753755..4fe008c 100644
--- a/lib/rules/negation.ts
+++ b/lib/rules/negation.ts
@@ -64,28 +64,14 @@ export default createRule("negation", {
 function getNegationText(
     node: EscapeCharacterSet | UnicodePropertyCharacterSet,
 ) {
-    let text: string
-    if (node.kind === "digit") {
-        text = "d"
-    } else if (node.kind === "space") {
-        text = "s"
-    } else if (node.kind === "word") {
-        text = "w"
-    } else if (node.kind === "property") {
-        text = "p"
+    // they are all of the form: /\\[dswp](?:\{[^{}]+\})?/
+    let kind = node.raw[1]
+
+    if (kind.toLowerCase() === kind) {
+        kind = kind.toUpperCase()
     } else {
-        throw new Error(`unknown kind:${node.kind}`)
-    }
-    if (!node.negate) {
-        text = text.toUpperCase()
-    }
-    if (node.kind === "property") {
-        if (node.value != null) {
-            text += `{${node.key}=${node.value}}`
-        } else {
-            text += `{${node.key}}`
-        }
+        kind = kind.toLowerCase()
     }
 
-    return `\\${text}`
+    return `\\${kind}${node.raw.slice(2)}`
 }
diff --git a/lib/rules/sort-alternatives.ts b/lib/rules/sort-alternatives.ts
index 40362f0..af88ffa 100644
--- a/lib/rules/sort-alternatives.ts
+++ b/lib/rules/sort-alternatives.ts
@@ -204,7 +204,7 @@ function trySortNumberAlternatives(alternatives: Alternative[]): void {
     {
         let start = 0
         for (let i = 0; i < alternatives.length; i++) {
-            if (!/^0|[1-9]\d*$/.test(alternatives[i].raw)) {
+            if (!/^(?:0|[1-9]\d*)$/.test(alternatives[i].raw)) {
                 if (start < i) {
                     numberRanges.push([start, i])
                 }
diff --git a/lib/utils/index.ts b/lib/utils/index.ts
index f94fc4a..c48614d 100644
--- a/lib/utils/index.ts
+++ b/lib/utils/index.ts
@@ -518,7 +518,7 @@ function buildRegExpHelperBase({
         toCharSet: (node, optionFlags) => {
             if (optionFlags) {
                 // Ignore the cache if the flag is specified.
-                return toCharSet(node, flags)
+                return toCharSet(node, optionFlags)
             }
 
             let charSet = cacheCharSet.get(node)
diff --git a/package-lock.json b/package-lock.json
index 38d2ad1..68cbb2e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1327,9 +1327,9 @@
             }
         },
         "@types/estree": {
-            "version": "0.0.49",
-            "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.49.tgz",
-            "integrity": "sha512-K1AFuMe8a+pXmfHTtnwBvqoEylNKVeaiKYkjmcEAdytMQVJ/i9Fu7sc13GxgXdO49gkE7Hy8SyJonUZUn+eVaw==",
+            "version": "0.0.50",
+            "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz",
+            "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==",
             "dev": true
         },
         "@types/glob": {
diff --git a/package.json b/package.json
index 3790304..98bf7cb 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,7 @@
         "@ota-meshi/eslint-plugin": "^0.7.0",
         "@types/eslint": "^7.2.0",
         "@types/eslint-scope": "^3.7.0",
-        "@types/estree": "^0.0.49",
+        "@types/estree": "^0.0.50",
         "@types/mocha": "^8.0.0",
         "@types/node": "^14.14.39",
         "@typescript-eslint/eslint-plugin": "^4.14.0",


Test patch:
diff --git a/tests/lib/rules/negation.ts b/tests/lib/rules/negation.ts
index dab7861..cdd1097 100644
--- a/tests/lib/rules/negation.ts
+++ b/tests/lib/rules/negation.ts
@@ -87,6 +87,13 @@ tester.run("negation", rule as any, {
                 "Unexpected negated character class. Use '\\p{Script=Hiragana}' instead.",
             ],
         },
+        {
+            code: String.raw`/[^\P{Ll}]/u;`,
+            output: String.raw`/\p{Ll}/u;`,
+            errors: [
+                "Unexpected negated character class. Use '\\p{Ll}' instead.",
+            ],
+        },
         {
             code: String.raw`const s ="[^\\w]"
             new RegExp(s)`,
diff --git a/tests/lib/rules/no-useless-flag.ts b/tests/lib/rules/no-useless-flag.ts
index 45eff00..3fae3c2 100644
--- a/tests/lib/rules/no-useless-flag.ts
+++ b/tests/lib/rules/no-useless-flag.ts
@@ -22,6 +22,7 @@ tester.run("no-useless-flag", rule as any, {
         `/\\b/iu`,
         String.raw`/\x41/i`,
         `/[a-zA-Z]/i`, // in that case you should use the i flag instead of removing it
+        `/\\p{Ll}/iu`,
 
         // m
         `/^foo/m`,