1
1
import type { RegExpVisitor } from "regexpp/visitor"
2
- import type { CharacterClass , CharacterClassRange } from "regexpp/ast"
3
2
import type { RegExpContext } from "../utils"
4
3
import {
5
4
createRule ,
6
5
defineRegexpVisitor ,
7
6
CP_DIGIT_ZERO ,
8
7
CP_DIGIT_NINE ,
9
8
} from "../utils"
9
+ import { Chars } from "regexp-ast-analysis"
10
10
11
11
export default createRule ( "prefer-d" , {
12
12
meta : {
@@ -28,38 +28,64 @@ export default createRule("prefer-d", {
28
28
*/
29
29
function createVisitor ( {
30
30
node,
31
+ flags,
31
32
getRegexpLocation,
32
33
fixReplaceNode,
34
+ toCharSet,
33
35
} : RegExpContext ) : RegExpVisitor . Handlers {
36
+ let reportedCharacterClass = false
37
+
34
38
return {
35
- onCharacterClassRangeEnter ( ccrNode : CharacterClassRange ) {
39
+ onCharacterClassEnter ( ccNode ) {
40
+ const charSet = toCharSet ( ccNode )
41
+
42
+ let predefined : string | undefined = undefined
43
+ if ( charSet . equals ( Chars . digit ( flags ) ) ) {
44
+ predefined = "\\d"
45
+ } else if ( charSet . equals ( Chars . digit ( flags ) . negate ( ) ) ) {
46
+ predefined = "\\D"
47
+ }
48
+
49
+ if ( predefined ) {
50
+ reportedCharacterClass = true
51
+
52
+ context . report ( {
53
+ node,
54
+ loc : getRegexpLocation ( ccNode ) ,
55
+ messageId : "unexpected" ,
56
+ data : {
57
+ type : "character class" ,
58
+ expr : ccNode . raw ,
59
+ instead : predefined ,
60
+ } ,
61
+ fix : fixReplaceNode ( ccNode , predefined ) ,
62
+ } )
63
+ }
64
+ } ,
65
+ onCharacterClassLeave ( ) {
66
+ reportedCharacterClass = false
67
+ } ,
68
+ onCharacterClassRangeEnter ( ccrNode ) {
69
+ if ( reportedCharacterClass ) {
70
+ return
71
+ }
72
+
36
73
if (
37
74
ccrNode . min . value === CP_DIGIT_ZERO &&
38
75
ccrNode . max . value === CP_DIGIT_NINE
39
76
) {
40
- let reportNode : CharacterClass | CharacterClassRange ,
41
- instead : string
42
- const ccNode = ccrNode . parent
43
- if ( ccNode . elements . length === 1 ) {
44
- reportNode = ccNode
45
- instead = ccNode . negate ? "\\D" : "\\d"
46
- } else {
47
- reportNode = ccrNode
48
- instead = "\\d"
49
- }
77
+ const instead = "\\d"
78
+
50
79
context . report ( {
51
80
node,
52
- loc : getRegexpLocation ( reportNode ) ,
81
+ loc : getRegexpLocation ( ccrNode ) ,
53
82
messageId : "unexpected" ,
54
83
data : {
55
- type :
56
- reportNode . type === "CharacterClass"
57
- ? "character class"
58
- : "character class range" ,
59
- expr : reportNode . raw ,
84
+ type : "character class range" ,
85
+ expr : ccrNode . raw ,
60
86
instead,
61
87
} ,
62
- fix : fixReplaceNode ( reportNode , instead ) ,
88
+ fix : fixReplaceNode ( ccrNode , instead ) ,
63
89
} )
64
90
}
65
91
} ,
0 commit comments