Skip to content

Commit

Permalink
fix(eslint-plugin): [prefer-includes] escape special characters (#7161)
Browse files Browse the repository at this point in the history
fix: escape special characters #7145
  • Loading branch information
Max10240 committed Jul 8, 2023
1 parent 6edaa04 commit 5a347a5
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 6 deletions.
33 changes: 27 additions & 6 deletions packages/eslint-plugin/src/rules/prefer-includes.ts
Expand Up @@ -124,6 +124,27 @@ export default createRule({
);
}

function escapeString(str: string): string {
const EscapeMap = {
'\0': '\\0',
"'": "\\'",
'\\': '\\\\',
'\n': '\\n',
'\r': '\\r',
'\v': '\\v',
'\t': '\\t',
'\f': '\\f',
// "\b" cause unexpected replacements
// '\b': '\\b',
};
const replaceRegex = new RegExp(Object.values(EscapeMap).join('|'), 'g');

return str.replace(
replaceRegex,
char => EscapeMap[char as keyof typeof EscapeMap],
);
}

function checkArrayIndexOf(
node: TSESTree.MemberExpression,
allowFixing: boolean,
Expand Down Expand Up @@ -202,12 +223,11 @@ export default createRule({
},

// /bar/.test(foo)
'CallExpression > MemberExpression.callee[property.name="test"][computed=false]'(
node: TSESTree.MemberExpression,
'CallExpression[arguments.length=1] > MemberExpression.callee[property.name="test"][computed=false]'(
node: TSESTree.MemberExpression & { parent: TSESTree.CallExpression },
): void {
const callNode = node.parent as TSESTree.CallExpression;
const text =
callNode.arguments.length === 1 ? parseRegExp(node.object) : null;
const callNode = node.parent;
const text = parseRegExp(node.object);
if (text == null) {
return;
}
Expand Down Expand Up @@ -237,13 +257,14 @@ export default createRule({
argNode.type !== AST_NODE_TYPES.CallExpression;

yield fixer.removeRange([callNode.range[0], argNode.range[0]]);
yield fixer.removeRange([argNode.range[1], callNode.range[1]]);
if (needsParen) {
yield fixer.insertTextBefore(argNode, '(');
yield fixer.insertTextAfter(argNode, ')');
}
yield fixer.insertTextAfter(
argNode,
`${node.optional ? '?.' : '.'}includes('${text}'`,
`${node.optional ? '?.' : '.'}includes('${escapeString(text)}')`,
);
},
});
Expand Down
27 changes: 27 additions & 0 deletions packages/eslint-plugin/tests/rules/prefer-includes.test.ts
Expand Up @@ -234,6 +234,33 @@ ruleTester.run('prefer-includes', rule, {
`,
errors: [{ messageId: 'preferStringIncludes' }],
},
// test SequenceExpression
{
code: `
function f(a: string): void {
/bar/.test((1 + 1, a));
}
`,
output: `
function f(a: string): void {
(1 + 1, a).includes('bar');
}
`,
errors: [{ messageId: 'preferStringIncludes' }],
},
{
code: `
function f(a: string): void {
/\\0'\\\\\\n\\r\\v\\t\\f/.test(a);
}
`,
output: `
function f(a: string): void {
a.includes('\\0\\'\\\\\\n\\r\\v\\t\\f');
}
`,
errors: [{ messageId: 'preferStringIncludes' }],
},
{
code: `
const pattern = new RegExp('bar');
Expand Down

0 comments on commit 5a347a5

Please sign in to comment.