🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

eslint-plugin-regexp

Package Overview
Dependencies
Maintainers
2
Versions
79
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-regexp - npm Package Compare versions

Comparing version

to
1.2.0

dist/rules/no-contradiction-with-assertion.js

15

dist/rules/control-character-escape.js

@@ -14,2 +14,12 @@ "use strict";

]);
function isRegExpLiteralAt({ node, patternSource }, at) {
if (utils_2.isRegexpLiteral(node)) {
return true;
}
const replaceRange = patternSource.getReplaceRange(at);
if (replaceRange && replaceRange.type === "RegExp") {
return true;
}
return false;
}
exports.default = utils_1.createRule("control-character-escape", {

@@ -30,3 +40,4 @@ meta: {

create(context) {
function createVisitor({ node, getRegexpLocation, fixReplaceNode, }) {
function createVisitor(regexpContext) {
const { node, getRegexpLocation, fixReplaceNode } = regexpContext;
return {

@@ -44,3 +55,3 @@ onCharacterEnter(cNode) {

}
if (!utils_2.isRegexpLiteral(node) &&
if (!isRegExpLiteralAt(regexpContext, cNode) &&
cNode.raw === String.fromCodePoint(cNode.value)) {

@@ -47,0 +58,0 @@ return;

7

dist/rules/negation.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const regexp_ast_analysis_1 = require("regexp-ast-analysis");
const utils_1 = require("../utils");

@@ -19,3 +20,3 @@ exports.default = utils_1.createRule("negation", {

create(context) {
function createVisitor({ node, getRegexpLocation, fixReplaceNode, toCharSet, flags, }) {
function createVisitor({ node, getRegexpLocation, fixReplaceNode, flags, }) {
return {

@@ -31,4 +32,4 @@ onCharacterClassEnter(ccNode) {

if (flags.ignoreCase && element.kind === "property") {
const ccSet = toCharSet(ccNode);
const negatedElementSet = toCharSet(Object.assign(Object.assign({}, element), { negate: !element.negate }));
const ccSet = regexp_ast_analysis_1.toCharSet(ccNode, flags);
const negatedElementSet = regexp_ast_analysis_1.toCharSet(Object.assign(Object.assign({}, element), { negate: !element.negate }), flags);
if (!ccSet.equals(negatedElementSet)) {

@@ -35,0 +36,0 @@ return;

@@ -7,3 +7,3 @@ "use strict";

const mention_1 = require("../utils/mention");
function groupElements(elements, { toCharSet }) {
function groupElements(elements, flags) {
const duplicates = [];

@@ -23,3 +23,3 @@ const characters = new Map();

for (const e of elements) {
const charSet = toCharSet(e);
const charSet = regexp_ast_analysis_1.toCharSet(e, flags);
if (e.type === "Character") {

@@ -168,6 +168,6 @@ const key = charSet.ranges[0].min;

function createVisitor(regexpContext) {
const { toCharSet, flags } = regexpContext;
const { flags } = regexpContext;
return {
onCharacterClassEnter(ccNode) {
const { duplicates, characters, characterRanges, characterSets, } = groupElements(ccNode.elements, regexpContext);
const { duplicates, characters, characterRanges, characterSets, } = groupElements(ccNode.elements, flags);
const rangesAndSets = [...characterRanges, ...characterSets];

@@ -181,3 +181,3 @@ const subsets = new Set();

for (const other of rangesAndSets) {
if (toCharSet(other).has(char.value)) {
if (regexp_ast_analysis_1.toCharSet(other, flags).has(char.value)) {
reportSubset(regexpContext, char, other);

@@ -194,3 +194,3 @@ subsets.add(char);

}
if (toCharSet(element).isSubsetOf(toCharSet(other))) {
if (regexp_ast_analysis_1.toCharSet(element, flags).isSubsetOf(regexp_ast_analysis_1.toCharSet(other, flags))) {
reportSubset(regexpContext, element, other);

@@ -209,8 +209,8 @@ subsets.add(element);

.filter((e) => !subsets.has(e) && e !== element)
.map((e) => toCharSet(e)));
const elementCharSet = toCharSet(element);
.map((e) => regexp_ast_analysis_1.toCharSet(e, flags)));
const elementCharSet = regexp_ast_analysis_1.toCharSet(element, flags);
if (elementCharSet.isSubsetOf(totalOthers)) {
const superSetElements = ccNode.elements
.filter((e) => !subsets.has(e) && e !== element)
.filter((e) => !toCharSet(e).isDisjointWith(elementCharSet));
.filter((e) => !regexp_ast_analysis_1.toCharSet(e, flags).isDisjointWith(elementCharSet));
reportSubsetOfMany(regexpContext, element, superSetElements);

@@ -230,3 +230,3 @@ subsets.add(element);

}
const intersection = toCharSet(range).intersect(toCharSet(other));
const intersection = regexp_ast_analysis_1.toCharSet(range, flags).intersect(regexp_ast_analysis_1.toCharSet(other, flags));
if (intersection.isEmpty) {

@@ -233,0 +233,0 @@ continue;

@@ -200,3 +200,3 @@ "use strict";

}
function* findDuplicationAstFast(alternatives, { toCharSet }) {
function* findDuplicationAstFast(alternatives, flags) {
const shortCircuit = (a) => {

@@ -209,3 +209,3 @@ return a.type === "CapturingGroup" ? false : null;

const other = alternatives[j];
if (regexp_ast_1.isEqualNodes(other, alternative, toCharSet, shortCircuit)) {
if (regexp_ast_1.isEqualNodes(other, alternative, flags, shortCircuit)) {
yield { type: "Duplicate", alternative, others: [other] };

@@ -216,8 +216,6 @@ }

}
function* findDuplicationAst(alternatives, context, hasNothingAfter) {
const { flags, toCharSet } = context;
function* findDuplicationAst(alternatives, flags, hasNothingAfter) {
const isCoveredOptions = {
flags,
canOmitRight: hasNothingAfter,
toCharSet,
};

@@ -227,3 +225,2 @@ const isCoveredOptionsNoPrefix = {

canOmitRight: false,
toCharSet,
};

@@ -235,3 +232,3 @@ for (let i = 0; i < alternatives.length; i++) {

if (regexp_ast_1.isCoveredNode(other, alternative, isCoveredOptions)) {
if (regexp_ast_1.isEqualNodes(other, alternative, toCharSet)) {
if (regexp_ast_1.isEqualNodes(other, alternative, flags)) {
yield {

@@ -280,3 +277,3 @@ type: "Duplicate",

}
function* findDuplicationNfa(alternatives, context, { hasNothingAfter, parser, ignoreOverlap }) {
function* findDuplicationNfa(alternatives, flags, { hasNothingAfter, parser, ignoreOverlap }) {
const previous = [];

@@ -309,3 +306,3 @@ for (let i = 0; i < alternatives.length; i++) {

case 3: {
const reorder = reorder_alternatives_1.canReorder([alternative, ...others], context);
const reorder = reorder_alternatives_1.canReorder([alternative, ...others], flags);
if (reorder) {

@@ -346,11 +343,11 @@ for (const other of others) {

}
function* findDuplication(alternatives, context, options) {
function* findDuplication(alternatives, flags, options) {
if (options.fastAst) {
yield* findDuplicationAstFast(alternatives, context);
yield* findDuplicationAstFast(alternatives, flags);
}
else {
yield* findDuplicationAst(alternatives, context, options.hasNothingAfter);
yield* findDuplicationAst(alternatives, flags, options.hasNothingAfter);
}
if (!options.noNfa) {
yield* findDuplicationNfa(alternatives, context, options);
yield* findDuplicationNfa(alternatives, flags, options);
}

@@ -487,3 +484,3 @@ }

const info = getFilterInfo(parentNode);
const rawResults = findDuplication(parentNode.alternatives, regexpContext, {
const rawResults = findDuplication(parentNode.alternatives, flags, {
fastAst: false,

@@ -490,0 +487,0 @@ noNfa: false,

@@ -108,6 +108,3 @@ "use strict";

}
const firstOf = regexp_ast_analysis_1.getFirstConsumedChar(assertion.alternatives, direction, flags);
if (firstOf.empty) {
return;
}
const firstOf = regexp_ast_analysis_1.FirstConsumedChars.toLook(regexp_ast_analysis_1.getFirstConsumedChar(assertion.alternatives, direction, flags));
const accept = assertion.negate ? "reject" : "accept";

@@ -114,0 +111,0 @@ const reject = assertion.negate ? "accept" : "reject";

@@ -6,2 +6,3 @@ "use strict";

const type_tracker_1 = require("../utils/type-tracker");
const regexp_ast_analysis_1 = require("regexp-ast-analysis");
class RegExpReference {

@@ -94,3 +95,3 @@ constructor(regExpContext) {

createVisitor(regExpContext) {
const { flags, regexpNode, toCharSet, ownsFlags, getFlagLocation, } = regExpContext;
const { flags, regexpNode, ownsFlags, getFlagLocation, } = regExpContext;
if (!flags.ignoreCase || !ownsFlags) {

@@ -111,3 +112,3 @@ return {};

if (unnecessary) {
if (toCharSet(cNode).size > 1) {
if (regexp_ast_analysis_1.toCharSet(cNode, flags).size > 1) {
unnecessary = false;

@@ -123,4 +124,4 @@ }

if (cNode.kind === "property") {
const caseInsensitive = toCharSet(cNode);
const caseSensitive = toCharSet(cNode, flagsNoI);
const caseInsensitive = regexp_ast_analysis_1.toCharSet(cNode, flags);
const caseSensitive = regexp_ast_analysis_1.toCharSet(cNode, flagsNoI);
if (!caseInsensitive.equals(caseSensitive)) {

@@ -127,0 +128,0 @@ unnecessary = false;

@@ -18,8 +18,8 @@ "use strict";

};
function getSingleConsumedChar(element, context) {
const empty = context.flags.unicode ? EMPTY_UNICODE : EMPTY_UTF16;
function getSingleConsumedChar(element, flags) {
const empty = flags.unicode ? EMPTY_UNICODE : EMPTY_UTF16;
switch (element.type) {
case "Alternative":
if (element.elements.length === 1) {
return getSingleConsumedChar(element.elements[0], context);
return getSingleConsumedChar(element.elements[0], flags);
}

@@ -31,3 +31,3 @@ return empty;

return {
char: context.toCharSet(element),
char: regexp_ast_analysis_1.toCharSet(element, flags),
complete: true,

@@ -37,3 +37,3 @@ };

case "CapturingGroup": {
const results = element.alternatives.map((a) => getSingleConsumedChar(a, context));
const results = element.alternatives.map((a) => getSingleConsumedChar(a, flags));
return {

@@ -76,3 +76,3 @@ char: empty.char.union(...results.map((r) => r.char)),

}
function getQuantifiersReplacement(left, right, context) {
function getQuantifiersReplacement(left, right, flags) {
if (left.min === left.max || right.min === right.max) {

@@ -84,10 +84,10 @@ return null;

}
const lSingle = getSingleConsumedChar(left.element, context);
const rSingle = getSingleConsumedChar(right.element, context);
const lSingle = getSingleConsumedChar(left.element, flags);
const rSingle = getSingleConsumedChar(right.element, flags);
const lPossibleChar = lSingle.complete
? lSingle.char
: regexp_ast_1.getPossiblyConsumedChar(left.element, context).char;
: regexp_ast_1.getPossiblyConsumedChar(left.element, flags).char;
const rPossibleChar = rSingle.complete
? rSingle.char
: regexp_ast_1.getPossiblyConsumedChar(right.element, context).char;
: regexp_ast_1.getPossiblyConsumedChar(right.element, flags).char;
const greedy = left.greedy;

@@ -160,9 +160,9 @@ let lQuant, rQuant;

}
function getQuantifierRepeatedElementReplacement(pair, context) {
function getQuantifierRepeatedElementReplacement(pair, flags) {
const [left, right] = pair;
const lSingle = getSingleConsumedChar(left.element, context);
const lSingle = getSingleConsumedChar(left.element, flags);
if (!lSingle.complete) {
return null;
}
const rSingle = getSingleConsumedChar(right.element, context);
const rSingle = getSingleConsumedChar(right.element, flags);
if (!rSingle.complete) {

@@ -189,3 +189,3 @@ return null;

}
function getNestedReplacement(dominate, nested, context) {
function getNestedReplacement(dominate, nested, flags) {
if (dominate.greedy !== nested.greedy) {

@@ -197,7 +197,7 @@ return null;

}
const single = getSingleConsumedChar(dominate.element, context);
const single = getSingleConsumedChar(dominate.element, flags);
if (single.char.isEmpty) {
return null;
}
const nestedPossible = regexp_ast_1.getPossiblyConsumedChar(nested.element, context);
const nestedPossible = regexp_ast_1.getPossiblyConsumedChar(nested.element, flags);
if (single.char.isSupersetOf(nestedPossible.char)) {

@@ -267,5 +267,5 @@ const { min } = nested;

}
function getReplacement(left, right, context) {
function getReplacement(left, right, flags) {
if (left.type === "Quantifier" && right.type === "Quantifier") {
const result = getQuantifiersReplacement(left, right, context);
const result = getQuantifiersReplacement(left, right, flags);
if (result && !ignoreReplacement(left, right, result))

@@ -277,3 +277,3 @@ return result;

if (rightRep) {
const result = getQuantifierRepeatedElementReplacement([left, rightRep], context);
const result = getQuantifierRepeatedElementReplacement([left, rightRep], flags);
if (result && !ignoreReplacement(left, right, result))

@@ -286,3 +286,3 @@ return result;

if (leftRep) {
const result = getQuantifierRepeatedElementReplacement([leftRep, right], context);
const result = getQuantifierRepeatedElementReplacement([leftRep, right], flags);
if (result && !ignoreReplacement(left, right, result))

@@ -294,3 +294,3 @@ return result;

for (const nested of nestedQuantifiers(right, "start")) {
const result = getNestedReplacement(left, nested, context);
const result = getNestedReplacement(left, nested, flags);
if (result)

@@ -302,3 +302,3 @@ return result;

for (const nested of nestedQuantifiers(left, "end")) {
const result = getNestedReplacement(right, nested, context);
const result = getNestedReplacement(right, nested, flags);
if (result)

@@ -337,3 +337,3 @@ return result;

function createVisitor(regexpContext) {
const { node, getRegexpLocation, fixReplaceNode } = regexpContext;
const { node, flags, getRegexpLocation, fixReplaceNode, } = regexpContext;
return {

@@ -344,3 +344,3 @@ onAlternativeEnter(aNode) {

const right = aNode.elements[i + 1];
const replacement = getReplacement(left, right, regexpContext);
const replacement = getReplacement(left, right, flags);
if (!replacement) {

@@ -347,0 +347,0 @@ continue;

@@ -62,3 +62,3 @@ "use strict";

}
function categorizeRawAlts(alternatives, { toCharSet }) {
function categorizeRawAlts(alternatives, flags) {
return alternatives.map((alternative) => {

@@ -74,3 +74,3 @@ if (alternative.elements.length === 1) {

element,
char: toCharSet(element),
char: regexp_ast_analysis_1.toCharSet(element, flags),
};

@@ -114,3 +114,3 @@ }

}
function parseRawAlts(alternatives, { flags, toCharSet }) {
function parseRawAlts(alternatives, flags) {
return alternatives.map((a) => {

@@ -123,3 +123,3 @@ if (a.isCharacter) {

elements,
char: toCharSet(a.element),
char: regexp_ast_analysis_1.toCharSet(a.element, flags),
raw: a.alternative.raw,

@@ -202,3 +202,3 @@ };

}
function totalIsAll(alternatives, { toCharSet }) {
function totalIsAll(alternatives, { flags }) {
let total = undefined;

@@ -208,6 +208,6 @@ for (const a of alternatives) {

if (total === undefined) {
total = toCharSet(a.element);
total = regexp_ast_analysis_1.toCharSet(a.element, flags);
}
else {
total = total.union(toCharSet(a.element));
total = total.union(regexp_ast_analysis_1.toCharSet(a.element, flags));
}

@@ -272,3 +272,3 @@ }

function createVisitor(regexpContext) {
const { node, getRegexpLocation, fixReplaceNode } = regexpContext;
const { node, flags, getRegexpLocation, fixReplaceNode, } = regexpContext;
function fixReplaceAlternatives(n, newAlternatives) {

@@ -291,3 +291,3 @@ const [prefix, suffix] = getParentPrefixAndSuffix(n);

}
const alts = categorizeRawAlts(n.alternatives, regexpContext);
const alts = categorizeRawAlts(n.alternatives, flags);
const characterAltsCount = alts.filter((a) => a.isCharacter)

@@ -308,3 +308,3 @@ .length;

}
const parsedAlts = parseRawAlts(alts, regexpContext);
const parsedAlts = parseRawAlts(alts, flags);
if (characterAltsCount >= 3 ||

@@ -311,0 +311,0 @@ containsCharacterClass(alts) ||

@@ -21,7 +21,7 @@ "use strict";

create(context) {
function createVisitor({ node, flags, getRegexpLocation, fixReplaceNode, toCharSet, }) {
function createVisitor({ node, flags, getRegexpLocation, fixReplaceNode, }) {
let reportedCharacterClass = false;
return {
onCharacterClassEnter(ccNode) {
const charSet = toCharSet(ccNode);
const charSet = regexp_ast_analysis_1.toCharSet(ccNode, flags);
let predefined = undefined;

@@ -28,0 +28,0 @@ if (charSet.equals(regexp_ast_analysis_1.Chars.digit(flags))) {

@@ -34,3 +34,3 @@ "use strict";

function createVisitor(regexpContext) {
const { node, flags, getRegexpLocation, toCharSet, fixReplaceNode, } = regexpContext;
const { node, flags, getRegexpLocation, fixReplaceNode, } = regexpContext;
const word = regexp_ast_analysis_1.Chars.word(flags);

@@ -120,3 +120,3 @@ const nonWord = regexp_ast_analysis_1.Chars.word(flags).negate();

}
const charSet = toCharSet(chars);
const charSet = regexp_ast_analysis_1.toCharSet(chars, flags);
if (charSet.isAll) {

@@ -123,0 +123,0 @@ replaceEdgeAssertion(aNode, false);

@@ -40,6 +40,6 @@ "use strict";

create(context) {
function createVisitor({ node, flags, getRegexpLocation, fixReplaceNode, patternSource, toCharSet, }) {
function createVisitor({ node, flags, getRegexpLocation, fixReplaceNode, patternSource, }) {
return {
onCharacterClassEnter(ccNode) {
const charSet = toCharSet(ccNode);
const charSet = regexp_ast_analysis_1.toCharSet(ccNode, flags);
let predefined = undefined;

@@ -46,0 +46,0 @@ if (charSet.equals(regexp_ast_analysis_1.Chars.word(flags))) {

@@ -8,2 +8,3 @@ "use strict";

const regexp_ast_1 = require("../utils/regexp-ast");
const alternative_prefix_1 = require("../utils/regexp-ast/alternative-prefix");
const cache = new Map();

@@ -40,5 +41,31 @@ function getAllowedChars(flags) {

function compareByteOrder(a, b) {
if (a === b) {
return 0;
}
return a < b ? -1 : +1;
}
function compareCharSets(a, b) {
if (a.isEmpty) {
return 1;
}
else if (b.isEmpty) {
return -1;
}
if (a.ranges[0].min !== b.ranges[0].min) {
return a.ranges[0].min - b.ranges[0].min;
}
const symDiff = a.union(b).without(a.intersect(b));
if (symDiff.isEmpty) {
return 0;
}
const min = symDiff.ranges[0].min;
if (a.has(min)) {
return -1;
}
return 1;
}
function compareCharSetStrings(a, b) {
const l = Math.min(a.length, b.length);
for (let i = 0; i < l; i++) {
const diff = a.charCodeAt(i) - b.charCodeAt(i);
const diff = compareCharSets(a[i], b[i]);
if (diff !== 0) {

@@ -50,6 +77,6 @@ return diff;

}
function sortAlternatives(alternatives, context) {
function sortAlternatives(alternatives, flags) {
const firstChars = new Map();
for (const a of alternatives) {
const chars = regexp_ast_analysis_1.getFirstConsumedChar(a, "ltr", context.flags);
const chars = regexp_ast_analysis_1.getFirstConsumedChar(a, "ltr", flags);
const char = chars.empty || chars.char.isEmpty

@@ -61,8 +88,7 @@ ? Infinity

alternatives.sort((a, b) => {
const firstA = firstChars.get(a);
const firstB = firstChars.get(b);
if (firstA !== firstB) {
return firstA - firstB;
const prefixDiff = compareCharSetStrings(alternative_prefix_1.getLongestPrefix(a, "ltr", flags), alternative_prefix_1.getLongestPrefix(b, "ltr", flags));
if (prefixDiff !== 0) {
return prefixDiff;
}
if (context.flags.ignoreCase) {
if (flags.ignoreCase) {
return (compareByteOrder(a.raw.toUpperCase(), b.raw.toUpperCase()) ||

@@ -147,3 +173,3 @@ compareByteOrder(a.raw, b.raw));

if (chars === undefined) {
chars = regexp_ast_1.getPossiblyConsumedChar(a, regexpContext).char;
chars = regexp_ast_1.getPossiblyConsumedChar(a, flags).char;
possibleCharsCache.set(a, chars);

@@ -155,4 +181,4 @@ }

const alternatives = run.elements;
if (reorder_alternatives_1.canReorder(alternatives, regexpContext)) {
sortAlternatives(alternatives, regexpContext);
if (reorder_alternatives_1.canReorder(alternatives, flags)) {
sortAlternatives(alternatives, flags);
trySortNumberAlternatives(alternatives);

@@ -166,3 +192,3 @@ }

if (elements.length > 1 &&
reorder_alternatives_1.canReorder(elements, regexpContext)) {
reorder_alternatives_1.canReorder(elements, flags)) {
trySortNumberAlternatives(elements);

@@ -169,0 +195,0 @@ alternatives.splice(index, elements.length, ...elements);

@@ -167,11 +167,17 @@ "use strict";

if (flagsArg.type !== "SpreadElement") {
flagsNode = flagsArg;
flagsString = ast_utils_1.getStringIfConstant(context, flagsArg);
ownsFlags = utils_1.isStringLiteral(flagsArg);
flagsNode = utils_1.dereferenceOwnedVariable(context, flagsArg);
flagsString = ast_utils_1.getStringIfConstant(context, flagsNode);
ownsFlags = utils_1.isStringLiteral(flagsNode);
}
}
else if (patternSource && patternSource.regexpValue) {
flagsString = patternSource.regexpValue.flags;
ownsFlags = Boolean(patternSource.regexpValue.ownedNode);
flagsNode = patternSource.regexpValue.ownedNode;
else {
if (patternSource && patternSource.regexpValue) {
flagsString = patternSource.regexpValue.flags;
ownsFlags = Boolean(patternSource.regexpValue.ownedNode);
flagsNode = patternSource.regexpValue.ownedNode;
}
else {
flagsString = "";
ownsFlags = true;
}
}

@@ -265,17 +271,4 @@ regexpDataList.push({

const sourceCode = context.getSourceCode();
const cacheCharSet = new WeakMap();
let cacheUsageOfPattern = null;
return {
toCharSet: (node, optionFlags) => {
if (optionFlags) {
return regexp_ast_analysis_1.toCharSet(node, optionFlags);
}
let charSet = cacheCharSet.get(node);
if (charSet) {
return charSet;
}
charSet = regexp_ast_analysis_1.toCharSet(node, flags);
cacheCharSet.set(node, charSet);
return charSet;
},
getRegexpLocation: (range, offsets) => {

@@ -305,7 +298,8 @@ if (offsets) {

patternSource,
flags,
flags: regexp_ast_analysis_1.toCache(flags),
};
}
function buildUnparsableRegExpContextBase({ patternSource, patternNode, regexpNode, context, flags, flagsString, flagsNode, ownsFlags, }) {
function buildUnparsableRegExpContextBase({ patternSource, patternNode, regexpNode, context, flags: originalFlags, flagsString, flagsNode, ownsFlags, }) {
const sourceCode = context.getSourceCode();
const flags = regexp_ast_analysis_1.toCache(originalFlags);
return {

@@ -349,2 +343,5 @@ regexpNode,

}
if (range[0] === range[1]) {
range[0]--;
}
return {

@@ -455,6 +452,17 @@ start: sourceCode.getLocFromIndex(range[0]),

}
const range = getFlagsRange(flagsNode);
if (range == null) {
return null;
let flagsFix;
if (flagsNode) {
const range = getFlagsRange(flagsNode);
if (range == null) {
return null;
}
flagsFix = fixer.replaceTextRange(range, newFlags);
}
else {
if (regexpNode.arguments.length !== 1) {
return null;
}
const end = regexpNode.range[1];
flagsFix = fixer.replaceTextRange([end - 1, end], `, "${newFlags}")`);
}
const patternRange = patternSource.getReplaceRange({

@@ -467,6 +475,3 @@ start: 0,

}
return [
patternRange.replace(fixer, patternSource.value),
fixer.replaceTextRange(range, newFlags),
];
return [patternRange.replace(fixer, patternSource.value), flagsFix];
};

@@ -473,0 +478,0 @@ }

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getFirstConsumedCharPlusAfter = void 0;
const regexp_ast_analysis_1 = require("regexp-ast-analysis");
function getFirstConsumedCharPlusAfter(element, direction, flags) {
const consumed = regexp_ast_analysis_1.getFirstConsumedChar(element, direction, flags);
if (!consumed.empty) {
return consumed;
}
return regexp_ast_analysis_1.FirstConsumedChars.concat([consumed, regexp_ast_analysis_1.getFirstConsumedCharAfter(element, direction, flags)], flags);
}
exports.getFirstConsumedCharPlusAfter = getFirstConsumedCharPlusAfter;

@@ -13,6 +13,8 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.getPossiblyConsumedChar = exports.extractCaptures = exports.getRegExpNodeFromExpression = void 0;
exports.getPossiblyConsumedChar = exports.extractCaptures = exports.getRegExpNodeFromExpression = exports.getFirstConsumedCharPlusAfter = void 0;
const regexpp_1 = require("regexpp");
const ast_utils_1 = require("../ast-utils");
const regexp_ast_analysis_1 = require("regexp-ast-analysis");
var common_1 = require("./common");
Object.defineProperty(exports, "getFirstConsumedCharPlusAfter", { enumerable: true, get: function () { return common_1.getFirstConsumedCharPlusAfter; } });
__exportStar(require("./is-covered"), exports);

@@ -59,3 +61,3 @@ __exportStar(require("./is-equals"), exports);

exports.extractCaptures = extractCaptures;
function getPossiblyConsumedChar(element, context) {
function getPossiblyConsumedChar(element, flags) {
const ranges = [];

@@ -67,3 +69,3 @@ let exact = true;

d.type === "CharacterSet") {
const c = context.toCharSet(d);
const c = regexp_ast_analysis_1.toCharSet(d, flags);
ranges.push(...c.ranges);

@@ -73,3 +75,3 @@ exact = exact && !c.isEmpty;

else if (d.type === "Backreference" && !regexp_ast_analysis_1.isEmptyBackreference(d)) {
const c = getPossiblyConsumedChar(d.resolved, context);
const c = getPossiblyConsumedChar(d.resolved, flags);
ranges.push(...c.char.ranges);

@@ -89,5 +91,5 @@ exact = exact && c.exact && c.char.size < 2;

});
const char = regexp_ast_analysis_1.Chars.empty(context.flags).union(ranges);
const char = regexp_ast_analysis_1.Chars.empty(flags).union(ranges);
return { char, exact };
}
exports.getPossiblyConsumedChar = getPossiblyConsumedChar;

@@ -5,2 +5,3 @@ "use strict";

const is_equals_1 = require("./is-equals");
const regexp_ast_analysis_1 = require("regexp-ast-analysis");
class NormalizedOther {

@@ -21,3 +22,3 @@ constructor(node) {

static fromElement(element, options) {
return new NormalizedCharacter(options.toCharSet(element));
return new NormalizedCharacter(regexp_ast_analysis_1.toCharSet(element, options.flags));
}

@@ -220,3 +221,3 @@ }

right.type === "NormalizedOther") {
return is_equals_1.isEqualNodes(left.node, right.node, options.toCharSet);
return is_equals_1.isEqualNodes(left.node, right.node, options.flags);
}

@@ -232,3 +233,3 @@ return false;

}
return is_equals_1.isEqualNodes(left.node, right.node, options.toCharSet);
return is_equals_1.isEqualNodes(left.node, right.node, options.flags);
}

@@ -235,0 +236,0 @@ return false;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isEqualNodes = void 0;
function isEqualChar(a, b, toCharSet) {
const regexp_ast_analysis_1 = require("regexp-ast-analysis");
function isEqualChar(a, b, flags) {
if (a.type === "Character") {

@@ -31,9 +32,9 @@ if (b.type === "Character") {

}
return toCharSet(a).equals(toCharSet(b));
return regexp_ast_analysis_1.toCharSet(a, flags).equals(regexp_ast_analysis_1.toCharSet(b, flags));
}
const EQUALS_CHECKER = {
Alternative(a, b, toCharSet, shortCircuit) {
return isEqualElements(a.elements, b.elements, toCharSet, shortCircuit);
Alternative(a, b, flags, shortCircuit) {
return isEqualElements(a.elements, b.elements, flags, shortCircuit);
},
Assertion(a, b, toCharSet, shortCircuit) {
Assertion(a, b, flags, shortCircuit) {
if (a.kind === "start" || a.kind === "end") {

@@ -47,3 +48,3 @@ return a.kind === b.kind;

if (b.kind === a.kind && a.negate === b.negate) {
return isEqualAlternatives(a.alternatives, b.alternatives, toCharSet, shortCircuit);
return isEqualAlternatives(a.alternatives, b.alternatives, flags, shortCircuit);
}

@@ -57,17 +58,17 @@ return false;

},
CapturingGroup(a, b, toCharSet, shortCircuit) {
CapturingGroup(a, b, flags, shortCircuit) {
return (a.name === b.name &&
isEqualAlternatives(a.alternatives, b.alternatives, toCharSet, shortCircuit));
isEqualAlternatives(a.alternatives, b.alternatives, flags, shortCircuit));
},
Character(a, b, toCharSet) {
return isEqualChar(a, b, toCharSet);
Character(a, b, flags) {
return isEqualChar(a, b, flags);
},
CharacterClass(a, b, toCharSet) {
return isEqualChar(a, b, toCharSet);
CharacterClass(a, b, flags) {
return isEqualChar(a, b, flags);
},
CharacterClassRange(a, b, toCharSet) {
return isEqualChar(a, b, toCharSet);
CharacterClassRange(a, b, flags) {
return isEqualChar(a, b, flags);
},
CharacterSet(a, b, toCharSet) {
return isEqualChar(a, b, toCharSet);
CharacterSet(a, b, flags) {
return isEqualChar(a, b, flags);
},

@@ -82,17 +83,17 @@ Flags(a, b) {

},
Group(a, b, toCharSet, shortCircuit) {
return isEqualAlternatives(a.alternatives, b.alternatives, toCharSet, shortCircuit);
Group(a, b, flags, shortCircuit) {
return isEqualAlternatives(a.alternatives, b.alternatives, flags, shortCircuit);
},
Pattern(a, b, toCharSet, shortCircuit) {
return isEqualAlternatives(a.alternatives, b.alternatives, toCharSet, shortCircuit);
Pattern(a, b, flags, shortCircuit) {
return isEqualAlternatives(a.alternatives, b.alternatives, flags, shortCircuit);
},
Quantifier(a, b, toCharSet, shortCircuit) {
Quantifier(a, b, flags, shortCircuit) {
return (a.min === b.min &&
a.max === b.max &&
a.greedy === b.greedy &&
isEqualNodes(a.element, b.element, toCharSet, shortCircuit));
isEqualNodes(a.element, b.element, flags, shortCircuit));
},
RegExpLiteral(a, b, toCharSet, shortCircuit) {
return (isEqualNodes(a.pattern, b.pattern, toCharSet, shortCircuit) &&
isEqualNodes(a.flags, b.flags, toCharSet, shortCircuit));
RegExpLiteral(a, b, flags, shortCircuit) {
return (isEqualNodes(a.pattern, b.pattern, flags, shortCircuit) &&
isEqualNodes(a.flags, b.flags, flags, shortCircuit));
},

@@ -106,5 +107,5 @@ };

}
function isEqualNodes(a, b, toCharSet, shortCircuit) {
function isEqualNodes(a, b, flags, shortCircuit) {
if (isToCharSetElement(a) && isToCharSetElement(b)) {
return isEqualChar(a, b, toCharSet);
return isEqualChar(a, b, flags);
}

@@ -121,3 +122,3 @@ if (a.type !== b.type) {

if (/[(*+?[\\{|]/.test(a.raw) || /[(*+?[\\{|]/.test(b.raw)) {
return EQUALS_CHECKER[a.type](a, b, toCharSet, shortCircuit);
return EQUALS_CHECKER[a.type](a, b, flags, shortCircuit);
}

@@ -127,3 +128,3 @@ return a.raw === b.raw;

exports.isEqualNodes = isEqualNodes;
function isEqualElements(a, b, toCharSet, shortCircuit) {
function isEqualElements(a, b, flags, shortCircuit) {
if (a.length !== b.length) {

@@ -135,3 +136,3 @@ return false;

const be = b[index];
if (!isEqualNodes(ae, be, toCharSet, shortCircuit)) {
if (!isEqualNodes(ae, be, flags, shortCircuit)) {
return false;

@@ -142,3 +143,3 @@ }

}
function isEqualAlternatives(a, b, toCharSet, shortCircuit) {
function isEqualAlternatives(a, b, flags, shortCircuit) {
if (a.length !== b.length) {

@@ -149,3 +150,3 @@ return false;

for (const ae of a) {
const bIndex = beList.findIndex((be) => isEqualNodes(ae, be, toCharSet, shortCircuit));
const bIndex = beList.findIndex((be) => isEqualNodes(ae, be, flags, shortCircuit));
if (bIndex >= 0) {

@@ -152,0 +153,0 @@ beList.splice(bIndex, 1);

@@ -6,3 +6,4 @@ "use strict";

const regexp_ast_analysis_1 = require("regexp-ast-analysis");
function canReorder(alternatives, context, options = {}) {
const alternative_prefix_1 = require("./regexp-ast/alternative-prefix");
function canReorder(alternatives, flags, options = {}) {
const { ignoreCapturingGroups = false, matchingDirection } = options;

@@ -16,4 +17,4 @@ const target = asSet(alternatives);

const eqClasses = dir === "unknown"
? getDirectionIndependedDeterminismEqClasses(slice, context)
: getDeterminismEqClasses(slice, dir, context);
? getDirectionIndependedDeterminismEqClasses(slice, flags)
: getDeterminismEqClasses(slice, dir, flags);
if (!ignoreCapturingGroups &&

@@ -31,3 +32,3 @@ !canReorderCapturingGroups(target, slice, eqClasses)) {

return (canReorderBasedOnLength(eq) ||
canReorderBasedOnConsumedChars(eq, context));
canReorderBasedOnConsumedChars(eq, flags));
});

@@ -66,13 +67,13 @@ }

}
function getDeterminismEqClasses(alternatives, dir, context) {
function getDeterminismEqClasses(alternatives, dir, flags) {
if (dir === "unknown") {
return getDirectionIndependedDeterminismEqClasses(alternatives, context);
return getDirectionIndependedDeterminismEqClasses(alternatives, flags);
}
return getDirectionalDeterminismEqClasses(alternatives, dir, context);
return getDirectionalDeterminismEqClasses(alternatives, dir, flags);
}
exports.getDeterminismEqClasses = getDeterminismEqClasses;
function getDirectionIndependedDeterminismEqClasses(alternatives, context) {
const ltr = getDirectionalDeterminismEqClasses(alternatives, "ltr", context);
const rtl = getDirectionalDeterminismEqClasses(alternatives, "rtl", context);
const disjoint = mergeOverlappingSets(new Set([...ltr, ...rtl]), (s) => s);
function getDirectionIndependedDeterminismEqClasses(alternatives, flags) {
const ltr = getDirectionalDeterminismEqClasses(alternatives, "ltr", flags);
const rtl = getDirectionalDeterminismEqClasses(alternatives, "rtl", flags);
const disjoint = mergeOverlappingSets([...ltr, ...rtl], (s) => s);
const result = [];

@@ -88,8 +89,9 @@ for (const sets of disjoint) {

}
function getDirectionalDeterminismEqClasses(alternatives, dir, context) {
function getDirectionalDeterminismEqClasses(alternatives, dir, flags) {
const getPrefixCharSets = cachedFn((a) => {
const prefix = getTopLevelAlternativePrefix(a, dir, context);
let prefix = alternative_prefix_1.getLongestPrefix(a, dir, flags);
let all = 0;
for (let i = prefix.length - 1; i >= 0; i--) {
if (prefix[i].isAll) {
prefix.pop();
all++;
}

@@ -100,2 +102,5 @@ else {

}
if (all > 0) {
prefix = prefix.slice(0, prefix.length - all);
}
return prefix;

@@ -116,8 +121,8 @@ });

function subdivide(eqClass, index) {
if (eqClass.size < 2) {
return [[...eqClass]];
if (eqClass.length < 2) {
return [eqClass];
}
for (const prefix of eqClass) {
if (index >= prefix.characters.length) {
return [[...eqClass]];
return [eqClass];
}

@@ -132,178 +137,72 @@ }

}
return subdivide(new Set(prefixes), 0).map((eq) => eq.map((p) => p.alternative));
return subdivide(prefixes, 0).map((eq) => eq.map((p) => p.alternative));
}
function* mergeOverlappingSets(sets, getElements) {
if (sets.size < 2) {
yield sets;
return;
}
const map = new Map();
let disjoint = true;
for (const s of sets) {
for (const e of getElements(s)) {
const entry = map.get(e);
if (entry === undefined) {
map.set(e, { type: "Set", set: new Set([s]) });
}
else if (entry.type === "Set") {
entry.set.add(s);
disjoint = false;
}
class SetEquivalence {
constructor(count) {
this.count = count;
this.indexes = [];
for (let i = 0; i < count; i++) {
this.indexes.push(i);
}
}
function resolve(key) {
let e = key;
for (;;) {
const entry = map.get(e);
if (entry && entry.type === "Ref") {
e = entry.key;
makeEqual(a, b) {
let aValue = this.indexes[a];
let bValue = this.indexes[b];
while (aValue !== bValue) {
if (aValue < bValue) {
this.indexes[b] = aValue;
b = bValue;
bValue = this.indexes[b];
}
else {
return e;
this.indexes[a] = bValue;
a = aValue;
aValue = this.indexes[a];
}
}
}
if (!disjoint) {
for (const s of sets) {
const toMergeSet = new Set();
for (const e of getElements(s)) {
toMergeSet.add(resolve(e));
getEquivalenceSets() {
let counter = 0;
for (let i = 0; i < this.count; i++) {
if (i === this.indexes[i]) {
this.indexes[i] = counter++;
}
if (toMergeSet.size < 2) {
continue;
else {
this.indexes[i] = this.indexes[this.indexes[i]];
}
const toMerge = [...toMergeSet];
const intoKey = toMerge[0];
const intoSet = map.get(intoKey);
for (let i = 1; i < toMerge.length; i++) {
const mergeKey = toMerge[i];
const mergeSet = map.get(mergeKey);
mergeSet.set.forEach((p) => intoSet.set.add(p));
map.set(mergeKey, { type: "Ref", key: intoKey });
}
}
return {
count: counter,
indexes: this.indexes,
};
}
for (const value of map.values()) {
if (value.type === "Set") {
yield value.set;
}
}
}
function getTopLevelAlternativePrefix(alternative, dir, context) {
const { prefix, complete } = getAlternativePrefix(alternative, dir, context);
if (complete) {
const last = dir === "ltr"
? alternative.elements[alternative.elements.length - 1]
: alternative.elements[0];
if (last) {
const cs = regexp_ast_analysis_1.getFirstCharAfter(last, dir, context.flags).char;
if (!cs.isEmpty) {
prefix.push(cs);
}
}
function mergeOverlappingSets(sets, getElements) {
if (sets.length < 2) {
return [sets];
}
return prefix;
}
function getAlternativePrefix(alternative, dir, context) {
const prefix = [];
const elements = dir === "ltr"
? alternative.elements
: [...alternative.elements].reverse();
let lastComplete = undefined;
for (const e of elements) {
if (regexp_ast_analysis_1.isZeroLength(e)) {
continue;
}
let elementPrefix;
switch (e.type) {
case "Character":
case "CharacterClass":
case "CharacterSet":
elementPrefix = getCharAlternativePrefix(e, dir, context);
break;
case "CapturingGroup":
case "Group":
elementPrefix = getGroupAlternativePrefix(e, dir, context);
break;
case "Quantifier":
elementPrefix = getQuantifierAlternativePrefix(e, dir, context);
break;
default:
elementPrefix = undefined;
}
if (elementPrefix) {
prefix.push(...elementPrefix.prefix);
if (!elementPrefix.complete) {
return { prefix, complete: false };
const eq = new SetEquivalence(sets.length);
const elementMap = new Map();
for (let i = 0; i < sets.length; i++) {
const s = sets[i];
for (const e of getElements(s)) {
const elementSet = elementMap.get(e);
if (elementSet === undefined) {
elementMap.set(e, i);
}
lastComplete = e;
}
else {
let cs;
if (lastComplete === undefined) {
const fcc = regexp_ast_analysis_1.getFirstConsumedChar(alternative, dir, context.flags);
cs = fcc.empty ? fcc.char.union(fcc.look.char) : fcc.char;
}
else {
cs = regexp_ast_analysis_1.getFirstCharAfter(lastComplete, dir, context.flags).char;
eq.makeEqual(i, elementSet);
}
if (!cs.isEmpty) {
prefix.push(cs);
}
return { prefix, complete: false };
}
}
return { prefix, complete: true };
}
function getGroupAlternativePrefix(group, dir, context) {
if (group.alternatives.length === 1) {
return getAlternativePrefix(group.alternatives[0], dir, context);
const eqSets = eq.getEquivalenceSets();
const result = [];
for (let i = 0; i < eqSets.count; i++) {
result.push([]);
}
return undefined;
}
function getCharAlternativePrefix(element, _dir, context) {
const cs = context.toCharSet(element);
if (cs.isEmpty) {
return undefined;
for (let i = 0; i < sets.length; i++) {
result[eqSets.indexes[i]].push(sets[i]);
}
return { prefix: [cs], complete: true };
return result;
}
function getQuantifierAlternativePrefix(quant, dir, context) {
if (quant.min > 100) {
return undefined;
}
if (quant.min < 1) {
return undefined;
}
let inner;
switch (quant.element.type) {
case "CapturingGroup":
case "Group":
inner = getGroupAlternativePrefix(quant.element, dir, context);
break;
case "Character":
case "CharacterClass":
case "CharacterSet":
inner = getCharAlternativePrefix(quant.element, dir, context);
break;
default:
inner = undefined;
}
if (!inner) {
return undefined;
}
if (!inner.complete || inner.prefix.length === 0) {
return inner;
}
const prefix = [];
for (let i = 0; i < quant.min; i++) {
prefix.push(...inner.prefix);
}
if (quant.min === quant.max) {
return { prefix, complete: true };
}
const after = regexp_ast_analysis_1.getFirstCharAfter(quant, dir, context.flags);
prefix.push(prefix[0].union(after.char));
return { prefix, complete: false };
}
function canReorderBasedOnLength(slice) {

@@ -313,3 +212,3 @@ const lengthRange = regexp_ast_analysis_1.getLengthRange(slice);

}
function canReorderBasedOnConsumedChars(slice, context) {
function canReorderBasedOnConsumedChars(slice, flags) {
if (slice.some(regexp_ast_analysis_1.isPotentiallyZeroLength)) {

@@ -322,5 +221,5 @@ return false;

}
const consumedChars = regexp_ast_analysis_1.Chars.empty(context.flags).union(...slice.map((a) => getConsumedChars(a, context)));
return (regexp_ast_analysis_1.getFirstCharAfter(parent, "rtl", context.flags).char.isDisjointWith(consumedChars) &&
regexp_ast_analysis_1.getFirstCharAfter(parent, "ltr", context.flags).char.isDisjointWith(consumedChars));
const consumedChars = regexp_ast_analysis_1.Chars.empty(flags).union(...slice.map((a) => getConsumedChars(a, flags)));
return (regexp_ast_analysis_1.getFirstCharAfter(parent, "rtl", flags).char.isDisjointWith(consumedChars) &&
regexp_ast_analysis_1.getFirstCharAfter(parent, "ltr", flags).char.isDisjointWith(consumedChars));
}

@@ -357,3 +256,3 @@ function getAlternativesSlice(set) {

}
function getConsumedChars(element, context) {
function getConsumedChars(element, flags) {
const sets = [];

@@ -364,10 +263,10 @@ regexp_ast_analysis_1.hasSomeDescendant(element, (d) => {

d.type === "CharacterSet") {
sets.push(context.toCharSet(d));
sets.push(regexp_ast_analysis_1.toCharSet(d, flags));
}
else if (d.type === "Backreference" && !regexp_ast_analysis_1.isEmptyBackreference(d)) {
sets.push(getConsumedChars(d.resolved, context));
sets.push(getConsumedChars(d.resolved, flags));
}
return false;
}, (d) => d.type !== "Assertion" && d.type !== "CharacterClass");
return regexp_ast_analysis_1.Chars.empty(context.flags).union(...sets);
return regexp_ast_analysis_1.Chars.empty(flags).union(...sets);
}

@@ -374,0 +273,0 @@ function containsCapturingGroup(node) {

@@ -14,2 +14,4 @@ "use strict";

const no_assertion_capturing_group_1 = __importDefault(require("../rules/no-assertion-capturing-group"));
const no_contradiction_with_assertion_1 = __importDefault(require("../rules/no-contradiction-with-assertion"));
const no_control_character_1 = __importDefault(require("../rules/no-control-character"));
const no_dupe_characters_character_class_1 = __importDefault(require("../rules/no-dupe-characters-character-class"));

@@ -19,2 +21,3 @@ const no_dupe_disjunctions_1 = __importDefault(require("../rules/no-dupe-disjunctions"));

const no_empty_capturing_group_1 = __importDefault(require("../rules/no-empty-capturing-group"));
const no_empty_character_class_1 = __importDefault(require("../rules/no-empty-character-class"));
const no_empty_group_1 = __importDefault(require("../rules/no-empty-group"));

@@ -27,2 +30,3 @@ const no_empty_lookarounds_assertion_1 = __importDefault(require("../rules/no-empty-lookarounds-assertion"));

const no_legacy_features_1 = __importDefault(require("../rules/no-legacy-features"));
const no_misleading_unicode_character_1 = __importDefault(require("../rules/no-misleading-unicode-character"));
const no_non_standard_flag_1 = __importDefault(require("../rules/no-non-standard-flag"));

@@ -59,3 +63,5 @@ const no_obscure_range_1 = __importDefault(require("../rules/no-obscure-range"));

const prefer_escape_replacement_dollar_char_1 = __importDefault(require("../rules/prefer-escape-replacement-dollar-char"));
const prefer_lookaround_1 = __importDefault(require("../rules/prefer-lookaround"));
const prefer_named_backreference_1 = __importDefault(require("../rules/prefer-named-backreference"));
const prefer_named_capture_group_1 = __importDefault(require("../rules/prefer-named-capture-group"));
const prefer_plus_quantifier_1 = __importDefault(require("../rules/prefer-plus-quantifier"));

@@ -72,2 +78,3 @@ const prefer_predefined_assertion_1 = __importDefault(require("../rules/prefer-predefined-assertion"));

const prefer_w_1 = __importDefault(require("../rules/prefer-w"));
const require_unicode_regexp_1 = __importDefault(require("../rules/require-unicode-regexp"));
const sort_alternatives_1 = __importDefault(require("../rules/sort-alternatives"));

@@ -86,2 +93,4 @@ const sort_character_class_elements_1 = __importDefault(require("../rules/sort-character-class-elements"));

no_assertion_capturing_group_1.default,
no_contradiction_with_assertion_1.default,
no_control_character_1.default,
no_dupe_characters_character_class_1.default,

@@ -91,2 +100,3 @@ no_dupe_disjunctions_1.default,

no_empty_capturing_group_1.default,
no_empty_character_class_1.default,
no_empty_group_1.default,

@@ -99,2 +109,3 @@ no_empty_lookarounds_assertion_1.default,

no_legacy_features_1.default,
no_misleading_unicode_character_1.default,
no_non_standard_flag_1.default,

@@ -131,3 +142,5 @@ no_obscure_range_1.default,

prefer_escape_replacement_dollar_char_1.default,
prefer_lookaround_1.default,
prefer_named_backreference_1.default,
prefer_named_capture_group_1.default,
prefer_plus_quantifier_1.default,

@@ -144,2 +157,3 @@ prefer_predefined_assertion_1.default,

prefer_w_1.default,
require_unicode_regexp_1.default,
sort_alternatives_1.default,

@@ -146,0 +160,0 @@ sort_character_class_elements_1.default,

{
"name": "eslint-plugin-regexp",
"version": "1.1.0",
"version": "1.2.0",
"description": "ESLint plugin for finding RegExp mistakes and RegExp style guide violations.",

@@ -84,3 +84,3 @@ "engines": {

"raw-loader": "^4.0.1",
"stylelint": "^13.6.1",
"stylelint": "^13.13.1",
"stylelint-config-standard": "^22.0.0",

@@ -97,5 +97,6 @@ "stylelint-plugin-stylus": "^0.11.0",

"eslint-utils": "^3.0.0",
"grapheme-splitter": "^1.0.4",
"jsdoctypeparser": "^9.0.0",
"refa": "^0.9.0",
"regexp-ast-analysis": "^0.2.4",
"regexp-ast-analysis": "^0.3.0",
"regexpp": "^3.2.0",

@@ -102,0 +103,0 @@ "scslre": "^0.1.6"

@@ -107,5 +107,8 @@ # Introduction

|:--------|:------------|:---|
| [regexp/no-contradiction-with-assertion](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-contradiction-with-assertion.html) | disallow elements that contradict assertions | |
| [regexp/no-control-character](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-control-character.html) | disallow control characters | |
| [regexp/no-dupe-disjunctions](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-dupe-disjunctions.html) | disallow duplicate disjunctions | :star: |
| [regexp/no-empty-alternative](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-alternative.html) | disallow alternatives without elements | :star: |
| [regexp/no-empty-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-capturing-group.html) | disallow capturing group that captures empty. | :star: |
| [regexp/no-empty-character-class](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-character-class.html) | disallow character classes that match no characters | |
| [regexp/no-empty-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-group.html) | disallow empty group | :star: |

@@ -116,2 +119,3 @@ | [regexp/no-empty-lookarounds-assertion](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-lookarounds-assertion.html) | disallow empty lookahead assertion or empty lookbehind assertion | :star: |

| [regexp/no-lazy-ends](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-lazy-ends.html) | disallow lazy quantifiers at the end of an expression | :star: |
| [regexp/no-misleading-unicode-character](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-misleading-unicode-character.html) | disallow multi-code-point characters in character classes and quantifiers | :wrench: |
| [regexp/no-optional-assertion](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-optional-assertion.html) | disallow optional assertions | :star: |

@@ -158,2 +162,3 @@ | [regexp/no-potentially-useless-backreference](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-potentially-useless-backreference.html) | disallow backreferences that reference a group that might not be matched | :star: |

| [regexp/prefer-regexp-test](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-regexp-test.html) | enforce that `RegExp#test` is used instead of `String#match` and `RegExp#exec` | :wrench: |
| [regexp/require-unicode-regexp](https://ota-meshi.github.io/eslint-plugin-regexp/rules/require-unicode-regexp.html) | enforce the use of the `u` flag | :wrench: |
| [regexp/sort-alternatives](https://ota-meshi.github.io/eslint-plugin-regexp/rules/sort-alternatives.html) | sort alternatives if order doesn't matter | :wrench: |

@@ -172,3 +177,5 @@

| [regexp/prefer-d](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-d.html) | enforce using `\d` | :star::wrench: |
| [regexp/prefer-lookaround](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-lookaround.html) | prefer lookarounds over capturing group that do not replace | :wrench: |
| [regexp/prefer-named-backreference](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-named-backreference.html) | enforce using named backreferences | :wrench: |
| [regexp/prefer-named-capture-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-named-capture-group.html) | enforce using named capture groups | |
| [regexp/prefer-plus-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-plus-quantifier.html) | enforce using `+` quantifier | :star::wrench: |

@@ -175,0 +182,0 @@ | [regexp/prefer-question-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-question-quantifier.html) | enforce using `?` quantifier | :star::wrench: |