1
+ import type { PatternRange } from "../utils/ast-utils/pattern-source"
1
2
import type { RegExpVisitor } from "regexpp/visitor"
2
3
import type { RegExpContext } from "../utils"
3
4
import {
@@ -21,6 +22,26 @@ const CONTROL_CHARS = new Map<number, string>([
21
22
[ CP_CR , "\\r" ] ,
22
23
] )
23
24
25
+ /**
26
+ * Returns whether the regex is represented by a RegExp literal in source code
27
+ * at the given range.
28
+ */
29
+ function isRegExpLiteralAt (
30
+ { node, patternSource } : RegExpContext ,
31
+ at : PatternRange ,
32
+ ) : boolean {
33
+ if ( isRegexpLiteral ( node ) ) {
34
+ return true
35
+ }
36
+
37
+ const replaceRange = patternSource . getReplaceRange ( at )
38
+ if ( replaceRange && replaceRange . type === "RegExp" ) {
39
+ return true
40
+ }
41
+
42
+ return false
43
+ }
44
+
24
45
export default createRule ( "control-character-escape" , {
25
46
meta : {
26
47
docs : {
@@ -40,11 +61,11 @@ export default createRule("control-character-escape", {
40
61
/**
41
62
* Create visitor
42
63
*/
43
- function createVisitor ( {
44
- node ,
45
- getRegexpLocation ,
46
- fixReplaceNode ,
47
- } : RegExpContext ) : RegExpVisitor . Handlers {
64
+ function createVisitor (
65
+ regexpContext : RegExpContext ,
66
+ ) : RegExpVisitor . Handlers {
67
+ const { node , getRegexpLocation , fixReplaceNode } = regexpContext
68
+
48
69
return {
49
70
onCharacterEnter ( cNode ) {
50
71
if ( cNode . parent . type === "CharacterClassRange" ) {
@@ -62,7 +83,7 @@ export default createRule("control-character-escape", {
62
83
return
63
84
}
64
85
if (
65
- ! isRegexpLiteral ( node ) &&
86
+ ! isRegExpLiteralAt ( regexpContext , cNode ) &&
66
87
cNode . raw === String . fromCodePoint ( cNode . value )
67
88
) {
68
89
// we allow the direct usage of control characters in
0 commit comments