From d6e59bc5ea5f4f166c542e235460d209ce2a5c43 Mon Sep 17 00:00:00 2001 From: RunDevelopment Date: Mon, 13 Sep 2021 16:24:53 +0200 Subject: [PATCH] Fix `control-character-escape` false negatives --- lib/rules/control-character-escape.ts | 33 +++++++++++++++++---- tests/lib/rules/control-character-escape.ts | 7 +++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/lib/rules/control-character-escape.ts b/lib/rules/control-character-escape.ts index a131ee25c..eb097051f 100644 --- a/lib/rules/control-character-escape.ts +++ b/lib/rules/control-character-escape.ts @@ -1,3 +1,4 @@ +import type { PatternRange } from "../utils/ast-utils/pattern-source" import type { RegExpVisitor } from "regexpp/visitor" import type { RegExpContext } from "../utils" import { @@ -21,6 +22,26 @@ const CONTROL_CHARS = new Map([ [CP_CR, "\\r"], ]) +/** + * Returns whether the regex is represented by a RegExp literal in source code + * at the given range. + */ +function isRegExpLiteralAt( + { node, patternSource }: RegExpContext, + at: PatternRange, +): boolean { + if (isRegexpLiteral(node)) { + return true + } + + const replaceRange = patternSource.getReplaceRange(at) + if (replaceRange && replaceRange.type === "RegExp") { + return true + } + + return false +} + export default createRule("control-character-escape", { meta: { docs: { @@ -40,11 +61,11 @@ export default createRule("control-character-escape", { /** * Create visitor */ - function createVisitor({ - node, - getRegexpLocation, - fixReplaceNode, - }: RegExpContext): RegExpVisitor.Handlers { + function createVisitor( + regexpContext: RegExpContext, + ): RegExpVisitor.Handlers { + const { node, getRegexpLocation, fixReplaceNode } = regexpContext + return { onCharacterEnter(cNode) { if (cNode.parent.type === "CharacterClassRange") { @@ -62,7 +83,7 @@ export default createRule("control-character-escape", { return } if ( - !isRegexpLiteral(node) && + !isRegExpLiteralAt(regexpContext, cNode) && cNode.raw === String.fromCodePoint(cNode.value) ) { // we allow the direct usage of control characters in diff --git a/tests/lib/rules/control-character-escape.ts b/tests/lib/rules/control-character-escape.ts index 5d7fb17ec..75ba623f1 100644 --- a/tests/lib/rules/control-character-escape.ts +++ b/tests/lib/rules/control-character-escape.ts @@ -108,5 +108,12 @@ tester.run("control-character-escape", rule as any, { "Unexpected control character escape '\\u0009' (U+0009). Use '\\t' instead.", ], }, + { + code: String.raw`RegExp("\t\r\n\0" + / /.source)`, + output: String.raw`RegExp("\t\r\n\0" + /\t/.source)`, + errors: [ + "Unexpected control character escape '\t' (U+0009). Use '\\t' instead.", + ], + }, ], })