Skip to content

Commit 4b01aa5

Browse files
Use regexp-ast-analysis's toCharSet everywhere (#323)
1 parent 750abbc commit 4b01aa5

19 files changed

+194
-231
lines changed

.eslintrc.js

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,6 @@ module.exports = {
3434

3535
"no-shadow": "off", // ts bug?
3636
"@typescript-eslint/no-shadow": "error",
37-
38-
// Rules for implementing this plugin.
39-
"no-restricted-imports": [
40-
"error",
41-
{
42-
paths: [
43-
{
44-
name: "regexp-ast-analysis",
45-
importNames: ["toCharSet"],
46-
message:
47-
"Please use toCharSet from RegExpContext instead.",
48-
},
49-
],
50-
},
51-
],
5237
},
5338
overrides: [
5439
{

lib/rules/negation.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { toCharSet } from "regexp-ast-analysis"
12
import type {
23
EscapeCharacterSet,
34
UnicodePropertyCharacterSet,
@@ -29,7 +30,6 @@ export default createRule("negation", {
2930
node,
3031
getRegexpLocation,
3132
fixReplaceNode,
32-
toCharSet,
3333
flags,
3434
}: RegExpContext): RegExpVisitor.Handlers {
3535
return {
@@ -53,12 +53,15 @@ export default createRule("negation", {
5353
// All other character sets are either case-invariant
5454
// (/./, /\s/, /\d/) or inconsistent (/\w/).
5555

56-
const ccSet = toCharSet(ccNode)
56+
const ccSet = toCharSet(ccNode, flags)
5757

58-
const negatedElementSet = toCharSet({
59-
...element,
60-
negate: !element.negate,
61-
})
58+
const negatedElementSet = toCharSet(
59+
{
60+
...element,
61+
negate: !element.negate,
62+
},
63+
flags,
64+
)
6265

6366
if (!ccSet.equals(negatedElementSet)) {
6467
// We cannot remove the negative

lib/rules/no-dupe-characters-character-class.ts

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ import {
1818
} from "../utils"
1919
import type { CharRange, CharSet } from "refa"
2020
import { JS } from "refa"
21-
// eslint-disable-next-line no-restricted-imports -- there's no way around it
22-
import { toCharSet as uncachedToCharSet } from "regexp-ast-analysis"
21+
import type { ReadonlyFlags } from "regexp-ast-analysis"
22+
import { toCharSet } from "regexp-ast-analysis"
2323
import type { Rule } from "eslint"
2424
import { mentionChar } from "../utils/mention"
2525

@@ -39,7 +39,7 @@ interface Grouping {
3939
*/
4040
function groupElements(
4141
elements: CharacterClassElement[],
42-
{ toCharSet }: RegExpContext,
42+
flags: ReadonlyFlags,
4343
): Grouping {
4444
const duplicates: Grouping["duplicates"] = []
4545
const characters = new Map<number, Character>()
@@ -68,7 +68,7 @@ function groupElements(
6868
}
6969

7070
for (const e of elements) {
71-
const charSet = toCharSet(e)
71+
const charSet = toCharSet(e, flags)
7272

7373
if (e.type === "Character") {
7474
const key = charSet.ranges[0].min
@@ -293,7 +293,7 @@ export default createRule("no-dupe-characters-character-class", {
293293
function createVisitor(
294294
regexpContext: RegExpContext,
295295
): RegExpVisitor.Handlers {
296-
const { toCharSet, flags } = regexpContext
296+
const { flags } = regexpContext
297297

298298
return {
299299
// eslint-disable-next-line complexity -- X
@@ -303,7 +303,7 @@ export default createRule("no-dupe-characters-character-class", {
303303
characters,
304304
characterRanges,
305305
characterSets,
306-
} = groupElements(ccNode.elements, regexpContext)
306+
} = groupElements(ccNode.elements, flags)
307307
const rangesAndSets = [...characterRanges, ...characterSets]
308308

309309
// keep track of all reported subset elements
@@ -318,7 +318,7 @@ export default createRule("no-dupe-characters-character-class", {
318318
// report characters that are already matched by some range or set
319319
for (const char of characters) {
320320
for (const other of rangesAndSets) {
321-
if (toCharSet(other).has(char.value)) {
321+
if (toCharSet(other, flags).has(char.value)) {
322322
reportSubset(regexpContext, char, other)
323323
subsets.add(char)
324324
break
@@ -334,7 +334,9 @@ export default createRule("no-dupe-characters-character-class", {
334334
}
335335

336336
if (
337-
toCharSet(element).isSubsetOf(toCharSet(other))
337+
toCharSet(element, flags).isSubsetOf(
338+
toCharSet(other, flags),
339+
)
338340
) {
339341
reportSubset(regexpContext, element, other)
340342
subsets.add(element)
@@ -345,7 +347,7 @@ export default createRule("no-dupe-characters-character-class", {
345347

346348
// character ranges and sets might be a subset of a combination of other elements
347349
// e.g. `b-d` is a subset of `a-cd-f`
348-
const characterTotal = uncachedToCharSet(
350+
const characterTotal = toCharSet(
349351
characters.filter((c) => !subsets.has(c)),
350352
flags,
351353
)
@@ -357,16 +359,16 @@ export default createRule("no-dupe-characters-character-class", {
357359
const totalOthers = characterTotal.union(
358360
...rangesAndSets
359361
.filter((e) => !subsets.has(e) && e !== element)
360-
.map((e) => toCharSet(e)),
362+
.map((e) => toCharSet(e, flags)),
361363
)
362364

363-
const elementCharSet = toCharSet(element)
365+
const elementCharSet = toCharSet(element, flags)
364366
if (elementCharSet.isSubsetOf(totalOthers)) {
365367
const superSetElements = ccNode.elements
366368
.filter((e) => !subsets.has(e) && e !== element)
367369
.filter(
368370
(e) =>
369-
!toCharSet(e).isDisjointWith(
371+
!toCharSet(e, flags).isDisjointWith(
370372
elementCharSet,
371373
),
372374
)
@@ -394,9 +396,10 @@ export default createRule("no-dupe-characters-character-class", {
394396
continue
395397
}
396398

397-
const intersection = toCharSet(range).intersect(
398-
toCharSet(other),
399-
)
399+
const intersection = toCharSet(
400+
range,
401+
flags,
402+
).intersect(toCharSet(other, flags))
400403
if (intersection.isEmpty) {
401404
continue
402405
}

lib/rules/no-dupe-disjunctions.ts

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ interface Options {
362362
*/
363363
function* findDuplicationAstFast(
364364
alternatives: Alternative[],
365-
{ toCharSet }: RegExpContext,
365+
flags: ReadonlyFlags,
366366
): Iterable<Result> {
367367
// eslint-disable-next-line func-style -- x
368368
const shortCircuit: Parameters<typeof isEqualNodes>[3] = (a) => {
@@ -375,7 +375,7 @@ function* findDuplicationAstFast(
375375
for (let j = 0; j < i; j++) {
376376
const other = alternatives[j]
377377

378-
if (isEqualNodes(other, alternative, toCharSet, shortCircuit)) {
378+
if (isEqualNodes(other, alternative, flags, shortCircuit)) {
379379
yield { type: "Duplicate", alternative, others: [other] }
380380
}
381381
}
@@ -387,20 +387,16 @@ function* findDuplicationAstFast(
387387
*/
388388
function* findDuplicationAst(
389389
alternatives: Alternative[],
390-
context: RegExpContext,
390+
flags: ReadonlyFlags,
391391
hasNothingAfter: boolean,
392392
): Iterable<Result> {
393-
const { flags, toCharSet } = context
394-
395393
const isCoveredOptions: Parameters<typeof isCoveredNode>[2] = {
396394
flags,
397395
canOmitRight: hasNothingAfter,
398-
toCharSet,
399396
}
400397
const isCoveredOptionsNoPrefix: Parameters<typeof isCoveredNode>[2] = {
401398
flags,
402399
canOmitRight: false,
403-
toCharSet,
404400
}
405401

406402
for (let i = 0; i < alternatives.length; i++) {
@@ -410,7 +406,7 @@ function* findDuplicationAst(
410406
const other = alternatives[j]
411407

412408
if (isCoveredNode(other, alternative, isCoveredOptions)) {
413-
if (isEqualNodes(other, alternative, toCharSet)) {
409+
if (isEqualNodes(other, alternative, flags)) {
414410
yield {
415411
type: "Duplicate",
416412
alternative,
@@ -484,7 +480,7 @@ function* findPrefixDuplicationNfa(
484480
*/
485481
function* findDuplicationNfa(
486482
alternatives: Alternative[],
487-
context: RegExpContext,
483+
flags: ReadonlyFlags,
488484
{ hasNothingAfter, parser, ignoreOverlap }: Options,
489485
): Iterable<Result> {
490486
const previous: [NFA, boolean, Alternative][] = []
@@ -528,10 +524,7 @@ function* findDuplicationNfa(
528524
break
529525

530526
case SubsetRelation.leftSupersetOfRight: {
531-
const reorder = canReorder(
532-
[alternative, ...others],
533-
context,
534-
)
527+
const reorder = canReorder([alternative, ...others], flags)
535528

536529
if (reorder) {
537530
// We are allowed to freely reorder the alternatives.
@@ -580,23 +573,19 @@ function* findDuplicationNfa(
580573
*/
581574
function* findDuplication(
582575
alternatives: Alternative[],
583-
context: RegExpContext,
576+
flags: ReadonlyFlags,
584577
options: Options,
585578
): Iterable<Result> {
586579
// AST-based approach
587580
if (options.fastAst) {
588-
yield* findDuplicationAstFast(alternatives, context)
581+
yield* findDuplicationAstFast(alternatives, flags)
589582
} else {
590-
yield* findDuplicationAst(
591-
alternatives,
592-
context,
593-
options.hasNothingAfter,
594-
)
583+
yield* findDuplicationAst(alternatives, flags, options.hasNothingAfter)
595584
}
596585

597586
// NFA-based approach
598587
if (!options.noNfa) {
599-
yield* findDuplicationNfa(alternatives, context, options)
588+
yield* findDuplicationNfa(alternatives, flags, options)
600589
}
601590
}
602591

@@ -830,7 +819,7 @@ export default createRule("no-dupe-disjunctions", {
830819

831820
const rawResults = findDuplication(
832821
parentNode.alternatives,
833-
regexpContext,
822+
flags,
834823
{
835824
fastAst: false,
836825
noNfa: false,

lib/rules/no-useless-flag.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
import { createTypeTracker } from "../utils/type-tracker"
2323
import type { RuleListener } from "../types"
2424
import type { Rule } from "eslint"
25+
import { toCharSet } from "regexp-ast-analysis"
2526

2627
type CodePathStack = {
2728
codePathId: string
@@ -191,7 +192,6 @@ function createUselessIgnoreCaseFlagVisitor(context: Rule.RuleContext) {
191192
const {
192193
flags,
193194
regexpNode,
194-
toCharSet,
195195
ownsFlags,
196196
getFlagLocation,
197197
} = regExpContext
@@ -217,7 +217,7 @@ function createUselessIgnoreCaseFlagVisitor(context: Rule.RuleContext) {
217217
if (unnecessary) {
218218
// all characters only accept themselves except if they
219219
// are case sensitive
220-
if (toCharSet(cNode).size > 1) {
220+
if (toCharSet(cNode, flags).size > 1) {
221221
unnecessary = false
222222
}
223223
}
@@ -233,7 +233,7 @@ function createUselessIgnoreCaseFlagVisitor(context: Rule.RuleContext) {
233233
unnecessary = false
234234
}
235235
if (cNode.kind === "property") {
236-
const caseInsensitive = toCharSet(cNode)
236+
const caseInsensitive = toCharSet(cNode, flags)
237237
const caseSensitive = toCharSet(cNode, flagsNoI)
238238

239239
if (!caseInsensitive.equals(caseSensitive)) {

0 commit comments

Comments
 (0)