From b8a21886d2b309d72a692e007a5076fce5c14ff3 Mon Sep 17 00:00:00 2001 From: RunDevelopment Date: Tue, 27 Jul 2021 13:00:49 +0200 Subject: [PATCH 1/2] Improve `no-dupe-disjunctions` by reordering alternatives --- lib/rules/no-dupe-disjunctions.ts | 28 ++++++++++++++++++++++--- tests/lib/rules/no-dupe-disjunctions.ts | 15 +++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/lib/rules/no-dupe-disjunctions.ts b/lib/rules/no-dupe-disjunctions.ts index 7af0fd649..f829cc38d 100644 --- a/lib/rules/no-dupe-disjunctions.ts +++ b/lib/rules/no-dupe-disjunctions.ts @@ -29,6 +29,7 @@ import { } from "regexp-ast-analysis" import { RegExpParser } from "regexpp" import { UsageOfPattern } from "../utils/get-usage-of-pattern" +import { canReorder } from "../utils/reorder-alternatives" type ParentNode = Group | CapturingGroup | Pattern | LookaroundAssertion @@ -482,6 +483,7 @@ function* findPrefixDuplicationNfa( */ function* findDuplicationNfa( alternatives: Alternative[], + context: RegExpContext, { hasNothingAfter, parser, ignoreOverlap }: Options, ): Iterable { const previous: [NFA, boolean, Alternative][] = [] @@ -524,9 +526,29 @@ function* findDuplicationNfa( yield { type: "Subset", alternative, others } break - case SubsetRelation.leftSupersetOfRight: - yield { type: "Superset", alternative, others } + case SubsetRelation.leftSupersetOfRight: { + const reorder = canReorder( + [alternative, ...others], + context, + { ignoreCapturingGroups: true }, + ) + + if (reorder) { + // We are allowed to freely reorder the alternatives. + // This means that we can reverse the order of our + // alternatives to convert the superset into a subset. + for (const other of others) { + yield { + type: "Subset", + alternative: other, + others: [alternative], + } + } + } else { + yield { type: "Superset", alternative, others } + } break + } case SubsetRelation.none: case SubsetRelation.unknown: @@ -574,7 +596,7 @@ function* findDuplication( // NFA-based approach if (!options.noNfa) { - yield* findDuplicationNfa(alternatives, options) + yield* findDuplicationNfa(alternatives, context, options) } } diff --git a/tests/lib/rules/no-dupe-disjunctions.ts b/tests/lib/rules/no-dupe-disjunctions.ts index a0465b409..628bf89a0 100644 --- a/tests/lib/rules/no-dupe-disjunctions.ts +++ b/tests/lib/rules/no-dupe-disjunctions.ts @@ -365,6 +365,21 @@ tester.run("no-dupe-disjunctions", rule as any, { }, { code: String(/\b(?:\d|foo|\w+)\b/), + errors: [ + { + message: + "Unexpected useless alternative. This alternative is a strict subset of '\\w+' and can be removed.", + column: 7, + }, + { + message: + "Unexpected useless alternative. This alternative is a strict subset of '\\w+' and can be removed.", + column: 10, + }, + ], + }, + { + code: String(/(?:\d|foo|\w+)a/), options: [{ report: "interesting" }], errors: [ "Unexpected superset. This alternative is a superset of '\\d|foo'. It might be possible to remove the other alternative(s).", From e0e617496637a21ac3455e917f08fefb33b3a477 Mon Sep 17 00:00:00 2001 From: RunDevelopment Date: Tue, 27 Jul 2021 13:04:45 +0200 Subject: [PATCH 2/2] Don't ignore capturing groups --- lib/rules/no-dupe-disjunctions.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/rules/no-dupe-disjunctions.ts b/lib/rules/no-dupe-disjunctions.ts index f829cc38d..93ccead8f 100644 --- a/lib/rules/no-dupe-disjunctions.ts +++ b/lib/rules/no-dupe-disjunctions.ts @@ -530,7 +530,6 @@ function* findDuplicationNfa( const reorder = canReorder( [alternative, ...others], context, - { ignoreCapturingGroups: true }, ) if (reorder) {