Skip to content

Commit eb23520

Browse files
authored
Convert regexes to use named groups (#513)
1 parent 8fd4dda commit eb23520

11 files changed

+45
-46
lines changed

package.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,6 @@
8585
"extends": [
8686
"plugin:eslint-plugin/all"
8787
],
88-
"rules": {
89-
"prefer-named-capture-group": "off"
90-
},
9188
"overrides": [
9289
{
9390
"files": "rules/utils/*.js",

rules/custom-error-definition.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const MESSAGE_ID_INVALID_EXPORT = 'invalidExport';
66

77
const nameRegexp = /^(?:[A-Z][\da-z]*)*Error$/;
88

9-
const getClassName = name => upperfirst(name).replace(/(error|)$/i, 'Error');
9+
const getClassName = name => upperfirst(name).replace(/(?:error|)$/i, 'Error');
1010

1111
const getConstructorMethod = className => `
1212
constructor() {

rules/escape-case.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,18 @@ const {
66

77
const getDocumentationUrl = require('./utils/get-documentation-url');
88

9-
const escapeWithLowercase = /((?:^|[^\\])(?:\\\\)*)\\(x[\da-f]{2}|u[\da-f]{4}|u{[\da-f]+})/;
10-
const escapePatternWithLowercase = /((?:^|[^\\])(?:\\\\)*)\\(x[\da-f]{2}|u[\da-f]{4}|u{[\da-f]+}|c[a-z])/;
9+
const escapeWithLowercase = /(?<before>(?:^|[^\\])(?:\\\\)*)\\(?<data>x[\da-f]{2}|u[\da-f]{4}|u{[\da-f]+})/;
10+
const escapePatternWithLowercase = /(?<before>(?:^|[^\\])(?:\\\\)*)\\(?<data>x[\da-f]{2}|u[\da-f]{4}|u{[\da-f]+}|c[a-z])/;
1111
const hasLowercaseCharacter = /[a-z]+/;
1212
const message = 'Use uppercase characters for the value of the escape sequence.';
1313

1414
const fix = (value, regexp) => {
1515
const results = regexp.exec(value);
1616

1717
if (results) {
18-
const prefix = results[1].length + 1;
19-
const fixedEscape = results[2].slice(0, 1) + results[2].slice(1).toUpperCase();
18+
const {before, data} = results.groups;
19+
const prefix = before.length + 1;
20+
const fixedEscape = data.slice(0, 1) + data.slice(1).toUpperCase();
2021
return (
2122
value.slice(0, results.index + prefix) +
2223
fixedEscape +
@@ -50,7 +51,7 @@ Record escaped node position in regexpp ASTNode. Returns undefined if not found.
5051

5152
const matches = node.raw.match(escapePatternWithLowercase);
5253

53-
if (matches && matches[2].slice(1).match(hasLowercaseCharacter)) {
54+
if (matches && matches.groups.data.slice(1).match(hasLowercaseCharacter)) {
5455
escapeNodePosition = [node.start, node.end];
5556
}
5657
}
@@ -90,7 +91,7 @@ const create = context => {
9091

9192
const matches = node.raw.match(escapeWithLowercase);
9293

93-
if (matches && matches[2].slice(1).match(hasLowercaseCharacter)) {
94+
if (matches && matches.groups.data.slice(1).match(hasLowercaseCharacter)) {
9495
context.report({
9596
node,
9697
message,

rules/expiring-todo-comments.js

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ const packageDependencies = {
2727
};
2828

2929
const DEPENDENCY_INCLUSION_RE = /^[+-]\s*@?\S+\/?\S+/;
30-
const VERSION_COMPARISON_RE = /^(@?\S\/?\S+)@(>|>=)(\d+(\.\d+){0,2}(-[\d\-a-z]+(\.[\d\-a-z]+)*)?(\+[\d\-a-z]+(\.[\d\-a-z]+)*)?)/i;
31-
const PKG_VERSION_RE = /^(>|>=)(\d+(\.\d+){0,2}(-[\d-a-z]+(\.[\d-a-z]+)*)?(\+[\d-a-z]+(\.[\d-a-z]+)*)?)\s*$/;
32-
const ISO8601_DATE = /(\d{4})-(\d{2})-(\d{2})/;
30+
const VERSION_COMPARISON_RE = /^(?<name>@?\S\/?\S+)@(?<condition>>|>=)(?<version>\d+(?:\.\d+){0,2}(?:-[\d\-a-z]+(?:\.[\d\-a-z]+)*)?(?:\+[\d\-a-z]+(?:\.[\d\-a-z]+)*)?)/i;
31+
const PKG_VERSION_RE = /^(?<condition>>|>=)(?<version>\d+(?:\.\d+){0,2}(?:-[\d-a-z]+(?:\.[\d-a-z]+)*)?(?:\+[\d-a-z]+(?:\.[\d-a-z]+)*)?)\s*$/;
32+
const ISO8601_DATE = /\d{4}-\d{2}-\d{2}/;
3333

3434
function parseTodoWithArguments(string, {terms}) {
3535
const lowerCaseString = string.toLowerCase();
@@ -40,14 +40,14 @@ function parseTodoWithArguments(string, {terms}) {
4040
return false;
4141
}
4242

43-
const TODO_ARGUMENT_RE = /\[([^}]+)]/i;
43+
const TODO_ARGUMENT_RE = /\[(?<rawArguments>[^}]+)]/i;
4444
const result = TODO_ARGUMENT_RE.exec(string);
4545

4646
if (!result) {
4747
return false;
4848
}
4949

50-
const rawArguments = result[1];
50+
const {rawArguments} = result.groups;
5151

5252
return rawArguments
5353
.split(',')
@@ -84,10 +84,10 @@ function parseArgument(argumentString) {
8484
}
8585

8686
if (hasPackage && VERSION_COMPARISON_RE.test(argumentString)) {
87-
const result = VERSION_COMPARISON_RE.exec(argumentString);
88-
const name = result[1].trim();
89-
const condition = result[2].trim();
90-
const version = result[3].trim();
87+
const {groups} = VERSION_COMPARISON_RE.exec(argumentString);
88+
const name = groups.name.trim();
89+
const condition = groups.condition.trim();
90+
const version = groups.version.trim();
9191

9292
const hasEngineKeyword = name.indexOf('engine:') === 0;
9393
const isNodeEngine = hasEngineKeyword && name === 'engine:node';
@@ -116,14 +116,13 @@ function parseArgument(argumentString) {
116116

117117
if (hasPackage && PKG_VERSION_RE.test(argumentString)) {
118118
const result = PKG_VERSION_RE.exec(argumentString);
119-
const condition = result[1].trim();
120-
const version = result[2].trim();
119+
const {condition, version} = result.groups;
121120

122121
return {
123122
type: 'packageVersions',
124123
value: {
125-
condition,
126-
version
124+
condition: condition.trim(),
125+
version: version.trim()
127126
}
128127
};
129128
}

rules/filename-case.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const getDocumentationUrl = require('./utils/get-documentation-url');
88
const cartesianProductSamples = require('./utils/cartesian-product-samples');
99

1010
const pascalCase = string => upperfirst(camelCase(string));
11-
const numberRegex = /(\d+)/;
11+
const numberRegex = /\d+/;
1212
const PLACEHOLDER = '\uFFFF\uFFFF\uFFFF';
1313
const PLACEHOLDER_REGEX = new RegExp(PLACEHOLDER, 'i');
1414
const isIgnoredChar = char => !/^[a-z\d-_$]$/i.test(char);
@@ -91,12 +91,10 @@ function fixFilename(words, caseFunctions, {leading, extension}) {
9191
return combinations.map(parts => `${leading}${parts.join('')}${extension}`);
9292
}
9393

94-
const leadingUnserscoresRegex = /^(_+)(.*)$/;
94+
const leadingUnserscoresRegex = /^(?<leading>_+)(?<tailing>.*)$/;
9595
function splitFilename(filename) {
96-
const result = leadingUnserscoresRegex.exec(filename);
97-
98-
const leading = (result && result[1]) || '';
99-
const tailing = (result && result[2]) || filename;
96+
const result = leadingUnserscoresRegex.exec(filename) || {groups: {}};
97+
const {leading = '', tailing = filename} = result.groups;
10098

10199
const words = [];
102100

rules/import-index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
'use strict';
22
const getDocumentationUrl = require('./utils/get-documentation-url');
33

4-
const regexp = /^(@.*?\/.*?|[./]+?.*?)\/(\.|(?:index(?:\.js)?))?$/;
4+
const regexp = /^(?<package>@.*?\/.*?|[./]+?.*?)\/(?:\.|(?:index(?:\.js)?))?$/;
55
const isImportingIndex = value => regexp.test(value);
6-
const normalize = value => value.replace(regexp, '$1');
6+
const normalize = value => value.replace(regexp, '$<package>');
77

88
const importIndex = (context, node, argument) => {
99
if (argument && isImportingIndex(argument.value)) {

rules/no-abusive-eslint-disable.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22
const getDocumentationUrl = require('./utils/get-documentation-url');
33

4-
const disableRegex = /^eslint-disable(-next-line|-line)?($|(\s+(@(?:[\w-]+\/){1,2})?[\w-]+)?)/;
4+
const disableRegex = /^eslint-disable(?:-next-line|-line)?(?<ruleId>$|(?:\s+(?:@(?:[\w-]+\/){1,2})?[\w-]+)?)/;
55

66
const create = context => ({
77
Program: node => {
@@ -11,7 +11,7 @@ const create = context => ({
1111

1212
if (
1313
result && // It's a eslint-disable comment
14-
!result[2] // But it did not specify any rules
14+
!result.groups.ruleId // But it did not specify any rules
1515
) {
1616
context.report({
1717
loc: {

rules/no-hex-escape.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
const getDocumentationUrl = require('./utils/get-documentation-url');
33

44
function checkEscape(context, node, value) {
5-
const fixedValue = typeof value === 'string' ? value.replace(/((?:^|[^\\])(?:\\\\)*)\\x/g, '$1\\u00') : value;
5+
const fixedValue = typeof value === 'string' ?
6+
value.replace(/(?<=(?:^|[^\\])(?:\\\\)*)\\x/g, '\\u00') :
7+
value;
68

79
if (value !== fixedValue) {
810
context.report({

rules/prefer-dataset.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ const getMethodName = memberExpression => memberExpression.property.name;
66

77
const getDataAttributeName = argument => {
88
if (argument.type === 'Literal') {
9-
return (argument.value.match(/^data-(.+)/) || ['', ''])[1];
9+
const matches = /^data-(?<name>.+)/.exec(argument.value);
10+
return matches ? matches.groups.name : '';
1011
}
1112

1213
return '';
1314
};
1415

1516
const parseNodeText = (context, argument) => context.getSourceCode().getText(argument);
1617

17-
const dashToCamelCase = string => string.replace(/-([a-z])/g, s => s[1].toUpperCase());
18+
const dashToCamelCase = string => string.replace(/-[a-z]/g, s => s[1].toUpperCase());
1819

1920
const getReplacement = (context, node, memberExpression, propertyName) => {
2021
const calleeObject = parseNodeText(context, memberExpression.object);

test/filename-case.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,13 @@ ruleTester.run('filename-case', rule, {
177177
{case: 'kebabCase', ignore: ['\\.(web|android|ios)\\.js$']}
178178
]),
179179
testCaseWithOptions('src/foo/FooBar.something.js', undefined, [
180-
{case: 'kebabCase', ignore: [/\.(web|android|ios|something)\.js$/u]}
180+
{case: 'kebabCase', ignore: [/\.(?:web|android|ios|something)\.js$/u]}
181181
]),
182182
testCaseWithOptions('src/foo/FooBar.js', undefined, [
183183
{case: 'kebabCase', ignore: ['^(F|f)oo']}
184184
]),
185185
testCaseWithOptions('src/foo/FooBar.js', undefined, [
186-
{case: 'kebabCase', ignore: [/^(F|f)oo/u]}
186+
{case: 'kebabCase', ignore: [/^[Ff]oo/u]}
187187
]),
188188
testCaseWithOptions('src/foo/FOOBAR.js', undefined, [
189189
{case: 'kebabCase', ignore: ['^FOO', 'BAZ\\.js$']}

0 commit comments

Comments
 (0)