@@ -3,100 +3,33 @@ const {visitIf} = require('enhance-visitors');
3
3
const util = require ( '../util' ) ;
4
4
const createAvaRule = require ( '../create-ava-rule' ) ;
5
5
6
- class MicroCorrecter {
7
- constructor ( words ) {
8
- this . words = new Set ( words ) ;
9
-
10
- const letters = new Set ( ) ;
11
- words . forEach ( word => word . split ( '' ) . forEach ( letter => letters . add ( letter ) ) ) ;
12
- this . letters = [ ...letters ] ;
13
- }
14
-
15
- edits ( word ) {
16
- const edits = [ ] ;
17
- const { length} = word ;
18
- const { letters} = this ;
19
-
20
- for ( let i = 0 ; i < length ; i ++ ) {
21
- edits . push ( word . slice ( 0 , i ) + word . slice ( i + 1 ) ) ; // Skip
22
- for ( const letter of letters ) {
23
- edits . push ( word . slice ( 0 , i ) + letter + word . slice ( i + 1 ) ) ; // Replace
24
- }
25
- }
26
-
27
- for ( let i = 1 ; i < length ; i ++ ) {
28
- edits . push ( word . slice ( 0 , i - 1 ) + word [ i ] + word [ i - 1 ] + word . slice ( i + 1 ) ) ; // Transposition
29
- }
30
-
31
- for ( let i = 0 ; i <= length ; i ++ ) {
32
- for ( const letter of letters ) {
33
- edits . push ( word . slice ( 0 , i ) + letter + word . slice ( i ) ) ; // Addition
34
- }
35
- }
36
-
37
- return edits ;
38
- }
39
-
40
- correct ( word , distance ) {
41
- const { words} = this ;
42
-
43
- if ( words . has ( word ) ) {
44
- return word ;
45
- }
46
-
47
- if ( distance > 0 ) {
48
- const edits = this . edits ( word ) ;
49
-
50
- for ( const edit of edits ) {
51
- if ( words . has ( edit ) ) {
52
- return edit ;
53
- }
54
- }
55
-
56
- if ( distance > 1 ) {
57
- for ( const edit of edits ) {
58
- const correction = this . correct ( edit , distance - 1 ) ;
59
- if ( correction !== undefined ) {
60
- return correction ;
61
- }
62
- }
63
- }
64
- }
65
- }
66
- }
67
-
68
- const nonMethods = new Set ( [
69
- 'context' ,
70
- 'title'
71
- ] ) ;
72
-
73
- const properties = new Set ( [
74
- ...nonMethods ,
75
- ...util . executionMethods ,
76
- 'skip'
77
- ] ) ;
78
-
79
- const correcter = new MicroCorrecter ( [ ...properties ] ) ;
6
+ const isMethod = name => util . executionMethods . has ( name ) ;
80
7
81
8
const isCallExpression = node =>
82
9
node . parent . type === 'CallExpression' &&
83
10
node . parent . callee === node ;
84
11
85
- const correctIfNeeded = ( name , context , node ) => {
86
- const correction = correcter . correct ( name , Math . max ( 0 , Math . min ( name . length - 2 , 2 ) ) ) ;
87
- if ( correction === undefined ) {
88
- return undefined ;
89
- }
90
-
91
- if ( correction !== name ) {
92
- context . report ( {
93
- node,
94
- message : `Misspelled \`.${ correction } \` as \`.${ name } \`.` ,
95
- fix : fixer => fixer . replaceText ( node . property , correction )
96
- } ) ;
97
- }
12
+ const getMemberStats = members => {
13
+ const initial = {
14
+ skip : [ ] ,
15
+ falsey : [ ] ,
16
+ method : [ ] ,
17
+ other : [ ]
18
+ } ;
19
+
20
+ return members . reduce ( ( res , member ) => {
21
+ if ( member === 'skip' ) {
22
+ res . skip . push ( member ) ;
23
+ } else if ( member === 'falsey' ) {
24
+ res . falsey . push ( member ) ;
25
+ } else if ( isMethod ( member ) ) {
26
+ res . method . push ( member ) ;
27
+ } else {
28
+ res . other . push ( member ) ;
29
+ }
98
30
99
- return correction ;
31
+ return res ;
32
+ } , initial ) ;
100
33
} ;
101
34
102
35
const create = context => {
@@ -125,62 +58,66 @@ const create = context => {
125
58
}
126
59
127
60
const members = util . getMembers ( node ) ;
61
+ const stats = getMemberStats ( members ) ;
62
+
63
+ if ( members [ 0 ] === 'context' ) {
64
+ // Anything is fine when of the form `t.context...`
65
+ if ( members . length === 1 && isCallExpression ( node ) ) {
66
+ // Except `t.context()`
67
+ context . report ( {
68
+ node,
69
+ message : 'Unknown assertion method `.context`.'
70
+ } ) ;
71
+ }
128
72
129
- let hadSkip = false ;
130
- let hadCall = false ;
131
- let needCall = true ;
132
- for ( const [ i , member ] of members . entries ( ) ) {
133
- const corrected = correctIfNeeded ( member , context , node ) ;
134
- if ( corrected === undefined ) {
135
- needCall = false ;
136
- if ( isCallExpression ( node ) ) {
137
- context . report ( {
138
- node,
139
- message : `Unknown assertion method \`.${ member } \`.`
140
- } ) ;
141
- } else {
142
- context . report ( {
143
- node,
144
- message : `Unknown member \`.${ member } \`. Use \`.context.${ member } \` instead.`
145
- } ) ;
146
- }
147
-
148
- break ;
149
- } else if ( i === 0 && nonMethods . has ( corrected ) ) {
150
- needCall = false ;
151
- if ( members . length === 1 && isCallExpression ( node ) ) {
152
- context . report ( {
153
- node,
154
- message : `Unknown assertion method \`.${ member } \`.`
155
- } ) ;
156
- }
157
-
158
- break ;
159
- } else if ( corrected === 'skip' ) {
160
- if ( hadSkip ) {
161
- context . report ( {
162
- node,
163
- message : 'Too many chained uses of `.skip`.'
164
- } ) ;
165
- }
166
-
167
- hadSkip = true ;
168
- } else {
169
- if ( hadCall ) {
170
- context . report ( {
171
- node,
172
- message : 'Can\'t chain assertion methods.'
173
- } ) ;
174
- }
73
+ return ;
74
+ }
175
75
176
- hadCall = true ;
76
+ if ( members [ 0 ] === 'title' ) {
77
+ // Anything is fine when of the form `t.title...`
78
+ if ( members . length === 1 && isCallExpression ( node ) ) {
79
+ // Except `t.title()`
80
+ context . report ( {
81
+ node,
82
+ message : 'Unknown assertion method `.title`.'
83
+ } ) ;
177
84
}
85
+
86
+ return ;
178
87
}
179
88
180
- if ( needCall && ! hadCall ) {
89
+ if ( isCallExpression ( node ) ) {
90
+ if ( stats . other . length > 0 ) {
91
+ context . report ( {
92
+ node,
93
+ message : `Unknown assertion method \`.${ stats . other [ 0 ] } \`.`
94
+ } ) ;
95
+ } else if ( stats . skip . length > 1 ) {
96
+ context . report ( {
97
+ node,
98
+ message : 'Too many chained uses of `.skip`.'
99
+ } ) ;
100
+ } else if ( stats . falsey . length > 0 ) {
101
+ context . report ( {
102
+ node,
103
+ message : 'Misspelled `.falsy` as `.falsey`.' ,
104
+ fix : fixer => fixer . replaceText ( node . property , 'falsy' )
105
+ } ) ;
106
+ } else if ( stats . method . length > 1 ) {
107
+ context . report ( {
108
+ node,
109
+ message : 'Can\'t chain assertion methods.'
110
+ } ) ;
111
+ } else if ( stats . method . length === 0 ) {
112
+ context . report ( {
113
+ node,
114
+ message : 'Missing assertion method.'
115
+ } ) ;
116
+ }
117
+ } else if ( stats . other . length > 0 ) {
181
118
context . report ( {
182
119
node,
183
- message : 'Missing assertion method.'
120
+ message : `Unknown member \`. ${ stats . other [ 0 ] } \`. Use \`.context. ${ stats . other [ 0 ] } \` instead.`
184
121
} ) ;
185
122
}
186
123
} )
0 commit comments