@cookshack/eslint-config 1.2.0 → 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
+ })