@cookshack/eslint-config 2.0.5 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,192 @@
1
+ import { Linter } from 'eslint'
2
+ import { plugins } from '../../index.js'
3
+ import { lastOst, ostString } from '../../plugins/init-before-use.js'
4
+
5
+ let linter, validCases, invalidCases, config
6
+
7
+ linter = new Linter()
8
+ validCases = []
9
+ invalidCases = []
10
+
11
+ config = [ { languageOptions: { ecmaVersion: 2025,
12
+ sourceType: 'module' },
13
+ plugins,
14
+ rules: { 'cookshack/init-before-use': 'error' } } ]
15
+
16
+ function tree
17
+ () {
18
+ let out
19
+
20
+ out = ostString(lastOst())
21
+ if (out.length)
22
+ return '=== Ordered Syntax Tree ===\n' + out
23
+ return ''
24
+ }
25
+
26
+ function _pass(tc) {
27
+ let messages
28
+
29
+ messages = linter.verify(tc.code, config)
30
+ if (messages.length > 0)
31
+ throw new Error('unexpected errors: ' + JSON.stringify(messages, null, 2) + '\n' + tree())
32
+ }
33
+
34
+ function _fail(tc) {
35
+ let messages
36
+
37
+ messages = linter.verify(tc.code, config)
38
+ if (messages.length == tc.errors.length)
39
+ return
40
+ throw new Error('expected ' + tc.errors.length + ' errors, got ' + messages.length + '\n' + JSON.stringify(messages, null, 2) + '\n' + tree())
41
+ }
42
+
43
+ function fail(message, code) {
44
+ let errors
45
+
46
+ if (Array.isArray(message))
47
+ errors = message.map(m => ({ messageId: m }))
48
+ else
49
+ errors = [ { messageId: message } ]
50
+
51
+ invalidCases.push({ code, errors })
52
+ }
53
+
54
+ function pass(code) {
55
+ validCases.push({ code })
56
+ }
57
+
58
+ pass('let x; x = 1')
59
+
60
+ pass('let x = 1; x')
61
+
62
+ pass('function f() { let x = 1; return x }')
63
+
64
+ pass('let x; function shadow() { let x = 2; return x } function shadow2() { let x = 3; return x } x = 1')
65
+
66
+ pass('for (let x in [1,2,3]) {}; let x = 1')
67
+
68
+ pass(`for (let tc of validCases)
69
+ globalThis.it(tc.code, () => _valid(tc))
70
+ `)
71
+
72
+ pass(`for (let tc of validCases)
73
+ globalThis.it(tc.code, () => _valid(tc))
74
+ for (let tc of invalidCases)
75
+ globalThis.it(tc.code, () => _invalid(tc))
76
+ `)
77
+
78
+ pass('let x; let y = { x: 1 }; x = 2')
79
+
80
+ pass('function x() { }')
81
+
82
+ pass(`function a1
83
+ () {
84
+ let p
85
+
86
+ function a2
87
+ () {
88
+ return p[p.length - 1]
89
+ }
90
+
91
+ p = []
92
+ return a2(0)
93
+ }`)
94
+
95
+ pass('let x = 1; --x')
96
+
97
+ pass('let x = 1; x++')
98
+
99
+ pass('let x = 1; x += 2')
100
+
101
+ pass("import globals from 'globals'")
102
+
103
+ pass('let x, y; y = () => { return x }; x = 1')
104
+
105
+ // it's actually an err, but we'd have to track assignments
106
+ pass('let x, y; y = () => { return x }; y(); x = 1')
107
+
108
+ pass('let i; for (i = addr; i < end; i++) {}')
109
+
110
+ pass('for (let i = 0; i < 16; i++) { }')
111
+
112
+ pass(`
113
+ for (let count = 0, i = 0; i < Ed.ctags.length; i++)
114
+ if (Ed.ctags[i].name.startsWith(word.text)) {
115
+ options.push({ label: Ed.ctags[i].name, type: Ed.ctags[i].kind })
116
+ if (count++ > 10)
117
+ break
118
+ }
119
+ `)
120
+
121
+ pass(`
122
+ function equal
123
+ () {
124
+ let two
125
+
126
+ function run
127
+ () {
128
+ console.log(two)
129
+ }
130
+
131
+ function open
132
+ () {
133
+ // the point is to test if this will accidentally be first write of two
134
+ two = 0
135
+ }
136
+
137
+ if (globalThis.x) {
138
+ two = 1
139
+ run()
140
+ }
141
+ }`)
142
+
143
+ fail('mustInit', 'let x')
144
+
145
+ fail('initBeforeUse', 'x; let x = 1')
146
+
147
+ fail('initBeforeUse', 'f(); let f = () => {}')
148
+
149
+ fail('mustInit', 'console.log(x); let x')
150
+
151
+ fail([ 'initBeforeUse', 'initBeforeUse' ], 'x; y; let x = 1; let y = 2')
152
+
153
+ fail('initBeforeUse', 'for (x in [1,2,3]) {}; let x = 1')
154
+
155
+ fail('mustInit', 'for (x in [1,2,3]) {}; let x')
156
+
157
+ fail('initBeforeUse', 'let x = f(); function f() { return x }')
158
+
159
+ fail('initBeforeUse', `function outer
160
+ (arg) {
161
+ let p
162
+
163
+ function inner
164
+ () {
165
+ p.focus()
166
+ }
167
+
168
+ if (arg) {
169
+ inner()
170
+ return
171
+ }
172
+
173
+ p = get()
174
+ inner()
175
+ }`)
176
+
177
+ fail('initBeforeUse', 'let x; x = f(x)')
178
+
179
+ fail('initBeforeUse', 'let x = 0; function shadow(y) { let x; x = shadow2(x) + y; return x } function shadow2(y) { let x = 3 + y; return x } shadow(x)')
180
+
181
+ fail('initBeforeUse', 'let x; --x')
182
+
183
+ fail('initBeforeUse', 'let x; x++')
184
+
185
+ fail('initBeforeUse', 'let x; x += 2')
186
+
187
+ globalThis.describe('init-before-use', () => {
188
+ for (let tc of validCases)
189
+ globalThis.it(tc.code, () => _pass(tc))
190
+ for (let tc of invalidCases)
191
+ globalThis.it(tc.code, () => _fail(tc))
192
+ })
@@ -472,6 +472,30 @@ function add
472
472
  READ Map pos 75
473
473
  WRITE classCache pos 80.4`)
474
474
 
475
+ pass(`function a1
476
+ () {
477
+ let p
478
+
479
+ function a2
480
+ () {
481
+ return p[p.length - 1]
482
+ }
483
+
484
+ p = []
485
+ return a2(0)
486
+ }`,
487
+ `SCOPE 1 GLOBAL pos 0
488
+ SCOPE 1.1 MODULE pos 0
489
+ LET a1 pos 9
490
+ SCOPE 1.1.1 FUNCTION pos 11 name a1
491
+ LET p pos 23
492
+ LET a2 pos 37
493
+ SCOPE 1.1.1.1 FUNCTION pos 39 name a2
494
+ READ p pos 58
495
+ READ p pos 60
496
+ WRITE p pos 87.4
497
+ READ a2 pos 97`)
498
+
475
499
  fail(1, 'let x = 1; function foo() { return x }',
476
500
  `SCOPE 1 GLOBAL pos 0
477
501
  SCOPE 1.1 MODULE pos 0
@@ -538,12 +562,14 @@ function f
538
562
  READ b pos 115
539
563
  SCOPE 1.1.1.1.1 FUNCTION pos 125
540
564
  LET d pos 125
565
+ READ c1 pos 138
541
566
  READ d pos 144
542
567
  WRITE c1 pos 145.4
543
568
  READ c1 pos 164
544
569
  SCOPE 1.1.1.2 BLOCK pos 174
545
570
  READ ok pos 185
546
571
  WRITE c2 pos 187.4
572
+ READ c2 pos 192
547
573
  READ ok pos 198
548
574
  READ ok pos 203
549
575
  WRITE c2 pos 205.4
@@ -0,0 +1,42 @@
1
+ import { RuleTester } from 'eslint'
2
+ import { plugins } from '../../index.js'
3
+
4
+ let ruleTester, validCases, invalidCases
5
+
6
+ ruleTester = new RuleTester()
7
+ validCases = []
8
+ invalidCases = []
9
+
10
+ function pass
11
+ (code) {
12
+ validCases.push({ code })
13
+ }
14
+
15
+ function fail
16
+ (count, code) {
17
+ let errors
18
+
19
+ errors = []
20
+ while (count > 0) {
21
+ errors.push({ messageId: 'risky' })
22
+ count--
23
+ }
24
+
25
+ invalidCases.push({ code, errors })
26
+ }
27
+
28
+ pass('if (x == y) { }')
29
+
30
+ pass('if (x != y) { }')
31
+
32
+ pass('if (x !== y) { }')
33
+
34
+ fail(1, 'if (x === y) { }')
35
+
36
+ fail(2, 'if (x === y || a === y || a > 4) { }')
37
+
38
+ globalThis.describe('use-risky-equal',
39
+ () => ruleTester.run('use-risky-equal',
40
+ plugins.cookshack.rules['use-risky-equal'],
41
+ { valid: validCases,
42
+ invalid: invalidCases }))
@@ -0,0 +1,108 @@
1
+ import { RuleTester } from 'eslint'
2
+ import { plugins } from '../../index.js'
3
+
4
+ let ruleTester, validCases, invalidCases
5
+
6
+ ruleTester = new RuleTester()
7
+ validCases = []
8
+ invalidCases = []
9
+
10
+ function pass
11
+ (code) {
12
+ validCases.push({ code })
13
+ }
14
+
15
+ function fail
16
+ (count, code) {
17
+ let errors
18
+
19
+ errors = []
20
+ while (count > 0) {
21
+ errors.push({ messageId: 'varDeclBlockStart' })
22
+ count--
23
+ }
24
+
25
+ invalidCases.push({ code, errors })
26
+ }
27
+
28
+ pass('let x = 1')
29
+
30
+ pass('var x = 1')
31
+
32
+ pass('const x = 1')
33
+
34
+ pass('{ let x = 1 }')
35
+
36
+ pass('{ var x = 1 }')
37
+
38
+ pass('{ const x = 1 }')
39
+
40
+ pass('{ let x = 1; let y = 2 }')
41
+
42
+ pass('{ let x, y }')
43
+
44
+ pass('{ let x; let y }')
45
+
46
+ pass('for (let i = 0; i < 10; i++) { }')
47
+
48
+ pass('for (var i = 0; i < 10; i++) { }')
49
+
50
+ pass('for (const i = 0; i < 10; i++) { }')
51
+
52
+ pass('for (let x of arr) { }')
53
+
54
+ pass('for (let x in obj) { }')
55
+
56
+ pass('for (var x in obj) { }')
57
+
58
+ pass('try { } catch (err) { }')
59
+
60
+ pass('function f() { let x }')
61
+
62
+ pass('function f() { var x }')
63
+
64
+ pass('function f() { const x = 1 }')
65
+
66
+ pass('{ { let x } }')
67
+
68
+ pass('{ { let x; let y } }')
69
+
70
+ fail(1, 'if (1) { x = 1; let y = 2 }')
71
+
72
+ fail(1, 'if (1) { x = 1; var y = 2 }')
73
+
74
+ fail(1, 'if (1) { x = 1; const y = 2 }')
75
+
76
+ fail(2, 'if (1) { x = 1; let y = 2; let z = 3 }')
77
+
78
+ fail(1, '{ x = 1; let y = 2 }')
79
+
80
+ fail(1, '{ x = 1; var y = 2 }')
81
+
82
+ fail(1, '{ x = 1; const y = 2 }')
83
+
84
+ fail(1, 'function f() { x = 1; let y = 2 }')
85
+
86
+ fail(1, 'function f() { x = 1; var y = 2 }')
87
+
88
+ fail(1, 'function f() { x = 1; const y = 2 }')
89
+
90
+ fail(1, '{ { x = 1; let y = 2 } }')
91
+
92
+ fail(1, 'if (1) { if (2) { x = 1; let y = 2 } }')
93
+
94
+ fail(1, 'while (1) { x = 1; let y = 2 }')
95
+
96
+ fail(1, 'for (let i = 0; i < 10; i++) { x = 1; let y = 2 }')
97
+
98
+ fail(1, '{ function f() {}; let x }')
99
+
100
+ fail(2, '{ function f() {}; let x; let y }')
101
+
102
+ fail(1, '{ function f() {}; function g() {}; let x }')
103
+
104
+ globalThis.describe('var-decl-block-start',
105
+ () => ruleTester.run('var-decl-block-start',
106
+ plugins.cookshack.rules['var-decl-block-start'],
107
+ { valid: validCases,
108
+ invalid: invalidCases }))