]> git.proxmox.com Git - pve-eslint.git/blob - eslint/tests/lib/rules/prefer-exponentiation-operator.js
import 7.12.1 upstream release
[pve-eslint.git] / eslint / tests / lib / rules / prefer-exponentiation-operator.js
1 /**
2 * @fileoverview Tests for the prefer-exponentiation-operator rule
3 * @author Milos Djermanovic
4 */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Requirements
10 //------------------------------------------------------------------------------
11
12 const rule = require("../../../lib/rules/prefer-exponentiation-operator");
13 const { RuleTester } = require("../../../lib/rule-tester");
14
15 //------------------------------------------------------------------------------
16 // Helpers
17 //------------------------------------------------------------------------------
18
19 /**
20 * Create an object for the invalid array
21 * @param {string} code source code
22 * @param {string} output fixed source code
23 * @returns {Object} result object
24 * @private
25 */
26 function invalid(code, output) {
27 return {
28 code,
29 output,
30 errors: [
31 {
32 messageId: "useExponentiation",
33 type: "CallExpression"
34 }
35 ]
36 };
37 }
38
39 //------------------------------------------------------------------------------
40 // Tests
41 //------------------------------------------------------------------------------
42
43 const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2020 } });
44
45 ruleTester.run("prefer-exponentiation-operator", rule, {
46 valid: [
47
48 // not Math.pow()
49 "Object.pow(a, b)",
50 "Math.max(a, b)",
51 "Math",
52 "Math(a, b)",
53 "pow",
54 "pow(a, b)",
55 "Math.pow",
56 "Math.Pow(a, b)",
57 "math.pow(a, b)",
58 "foo.Math.pow(a, b)",
59 "new Math.pow(a, b)",
60 "Math[pow](a, b)",
61 { code: "globalThis.Object.pow(a, b)", env: { es2020: true } },
62 { code: "globalThis.Math.max(a, b)", env: { es2020: true } },
63
64 // not the global Math
65 "/* globals Math:off*/ Math.pow(a, b)",
66 "let Math; Math.pow(a, b);",
67 "if (foo) { const Math = 1; Math.pow(a, b); }",
68 "var x = function Math() { Math.pow(a, b); }",
69 "function foo(Math) { Math.pow(a, b); }",
70 "function foo() { Math.pow(a, b); var Math; }",
71
72 "globalThis.Math.pow(a, b)",
73 { code: "globalThis.Math.pow(a, b)", env: { es6: true } },
74 { code: "globalThis.Math.pow(a, b)", env: { es2017: true } },
75 {
76 code: `
77 var globalThis = bar;
78 globalThis.Math.pow(a, b)
79 `,
80 env: { es2020: true }
81 }
82 ],
83
84 invalid: [
85
86 invalid("Math.pow(a, b)", "a**b"),
87 invalid("(Math).pow(a, b)", "a**b"),
88 invalid("Math['pow'](a, b)", "a**b"),
89 invalid("(Math)['pow'](a, b)", "a**b"),
90 invalid("var x=Math\n. pow( a, \n b )", "var x=a**b"),
91 {
92 code: "globalThis.Math.pow(a, b)",
93 output: "a**b",
94 env: { es2020: true },
95 errors: [
96 {
97 messageId: "useExponentiation",
98 type: "CallExpression",
99 line: 1,
100 column: 1,
101 endLine: 1,
102 endColumn: 26
103 }
104 ]
105 },
106 {
107 code: "globalThis.Math['pow'](a, b)",
108 output: "a**b",
109 env: { es2020: true },
110 errors: [
111 {
112 messageId: "useExponentiation",
113 type: "CallExpression",
114 line: 1,
115 column: 1,
116 endLine: 1,
117 endColumn: 29
118 }
119 ]
120 },
121
122 // able to catch some workarounds
123 invalid("Math[`pow`](a, b)", "a**b"),
124 invalid("Math[`${'pow'}`](a, b)", "a**b"),
125 invalid("Math['p' + 'o' + 'w'](a, b)", "a**b"),
126
127 // non-expression parents that don't require parens
128 invalid("var x = Math.pow(a, b);", "var x = a**b;"),
129 invalid("if(Math.pow(a, b)){}", "if(a**b){}"),
130 invalid("for(;Math.pow(a, b);){}", "for(;a**b;){}"),
131 invalid("switch(foo){ case Math.pow(a, b): break; }", "switch(foo){ case a**b: break; }"),
132 invalid("{ foo: Math.pow(a, b) }", "{ foo: a**b }"),
133 invalid("function foo(bar, baz = Math.pow(a, b), quux){}", "function foo(bar, baz = a**b, quux){}"),
134 invalid("`${Math.pow(a, b)}`", "`${a**b}`"),
135
136 // non-expression parents that do require parens
137 invalid("class C extends Math.pow(a, b) {}", "class C extends (a**b) {}"),
138
139 // parents with a higher precedence
140 invalid("+ Math.pow(a, b)", "+ (a**b)"),
141 invalid("- Math.pow(a, b)", "- (a**b)"),
142 invalid("! Math.pow(a, b)", "! (a**b)"),
143 invalid("typeof Math.pow(a, b)", "typeof (a**b)"),
144 invalid("void Math.pow(a, b)", "void (a**b)"),
145 invalid("Math.pow(a, b) .toString()", "(a**b) .toString()"),
146 invalid("Math.pow(a, b) ()", "(a**b) ()"),
147 invalid("Math.pow(a, b) ``", "(a**b) ``"),
148 invalid("(class extends Math.pow(a, b) {})", "(class extends (a**b) {})"),
149
150 // already parenthesised, shouldn't insert extra parens
151 invalid("+(Math.pow(a, b))", "+(a**b)"),
152 invalid("(Math.pow(a, b)).toString()", "(a**b).toString()"),
153 invalid("(class extends (Math.pow(a, b)) {})", "(class extends (a**b) {})"),
154 invalid("class C extends (Math.pow(a, b)) {}", "class C extends (a**b) {}"),
155
156 // parents with a higher precedence, but the expression's role doesn't require parens
157 invalid("f(Math.pow(a, b))", "f(a**b)"),
158 invalid("f(foo, Math.pow(a, b))", "f(foo, a**b)"),
159 invalid("f(Math.pow(a, b), foo)", "f(a**b, foo)"),
160 invalid("f(foo, Math.pow(a, b), bar)", "f(foo, a**b, bar)"),
161 invalid("new F(Math.pow(a, b))", "new F(a**b)"),
162 invalid("new F(foo, Math.pow(a, b))", "new F(foo, a**b)"),
163 invalid("new F(Math.pow(a, b), foo)", "new F(a**b, foo)"),
164 invalid("new F(foo, Math.pow(a, b), bar)", "new F(foo, a**b, bar)"),
165 invalid("obj[Math.pow(a, b)]", "obj[a**b]"),
166 invalid("[foo, Math.pow(a, b), bar]", "[foo, a**b, bar]"),
167
168 // parents with a lower precedence
169 invalid("a * Math.pow(b, c)", "a * b**c"),
170 invalid("Math.pow(a, b) * c", "a**b * c"),
171 invalid("a + Math.pow(b, c)", "a + b**c"),
172 invalid("Math.pow(a, b)/c", "a**b/c"),
173 invalid("a < Math.pow(b, c)", "a < b**c"),
174 invalid("Math.pow(a, b) > c", "a**b > c"),
175 invalid("a === Math.pow(b, c)", "a === b**c"),
176 invalid("a ? Math.pow(b, c) : d", "a ? b**c : d"),
177 invalid("a = Math.pow(b, c)", "a = b**c"),
178 invalid("a += Math.pow(b, c)", "a += b**c"),
179 invalid("function *f() { yield Math.pow(a, b) }", "function *f() { yield a**b }"),
180 invalid("a, Math.pow(b, c), d", "a, b**c, d"),
181
182 // '**' is right-associative, that applies to both parent and child nodes
183 invalid("a ** Math.pow(b, c)", "a ** b**c"),
184 invalid("Math.pow(a, b) ** c", "(a**b) ** c"),
185 invalid("Math.pow(a, b ** c)", "a**b ** c"),
186 invalid("Math.pow(a ** b, c)", "(a ** b)**c"),
187 invalid("a ** Math.pow(b ** c, d ** e) ** f", "a ** ((b ** c)**d ** e) ** f"),
188
189 // doesn't remove already existing unnecessary parens around the whole expression
190 invalid("(Math.pow(a, b))", "(a**b)"),
191 invalid("foo + (Math.pow(a, b))", "foo + (a**b)"),
192 invalid("(Math.pow(a, b)) + foo", "(a**b) + foo"),
193 invalid("`${(Math.pow(a, b))}`", "`${(a**b)}`"),
194
195 // base and exponent with a higher precedence
196 invalid("Math.pow(2, 3)", "2**3"),
197 invalid("Math.pow(a.foo, b)", "a.foo**b"),
198 invalid("Math.pow(a, b.foo)", "a**b.foo"),
199 invalid("Math.pow(a(), b)", "a()**b"),
200 invalid("Math.pow(a, b())", "a**b()"),
201 invalid("Math.pow(++a, ++b)", "++a**++b"),
202 invalid("Math.pow(a++, ++b)", "a++**++b"),
203 invalid("Math.pow(a--, b--)", "a--**b--"),
204 invalid("Math.pow(--a, b--)", "--a**b--"),
205
206 // doesn't preserve unnecessary parens around base and exponent
207 invalid("Math.pow((a), (b))", "a**b"),
208 invalid("Math.pow(((a)), ((b)))", "a**b"),
209 invalid("Math.pow((a.foo), b)", "a.foo**b"),
210 invalid("Math.pow(a, (b.foo))", "a**b.foo"),
211 invalid("Math.pow((a()), b)", "a()**b"),
212 invalid("Math.pow(a, (b()))", "a**b()"),
213
214 // unary expressions are exception by the language - parens are required for the base to disambiguate operator precedence
215 invalid("Math.pow(+a, b)", "(+a)**b"),
216 invalid("Math.pow(a, +b)", "a**+b"),
217 invalid("Math.pow(-a, b)", "(-a)**b"),
218 invalid("Math.pow(a, -b)", "a**-b"),
219 invalid("Math.pow(-2, 3)", "(-2)**3"),
220 invalid("Math.pow(2, -3)", "2**-3"),
221
222 // base and exponent with a lower precedence
223 invalid("Math.pow(a * b, c)", "(a * b)**c"),
224 invalid("Math.pow(a, b * c)", "a**(b * c)"),
225 invalid("Math.pow(a / b, c)", "(a / b)**c"),
226 invalid("Math.pow(a, b / c)", "a**(b / c)"),
227 invalid("Math.pow(a + b, 3)", "(a + b)**3"),
228 invalid("Math.pow(2, a - b)", "2**(a - b)"),
229 invalid("Math.pow(a + b, c + d)", "(a + b)**(c + d)"),
230 invalid("Math.pow(a = b, c = d)", "(a = b)**(c = d)"),
231 invalid("Math.pow(a += b, c -= d)", "(a += b)**(c -= d)"),
232 invalid("Math.pow((a, b), (c, d))", "(a, b)**(c, d)"),
233 invalid("function *f() { Math.pow(yield, yield) }", "function *f() { (yield)**(yield) }"),
234
235 // doesn't put extra parens
236 invalid("Math.pow((a + b), (c + d))", "(a + b)**(c + d)"),
237
238 // tokens that can be adjacent
239 invalid("a+Math.pow(b, c)+d", "a+b**c+d"),
240
241 // tokens that cannot be adjacent
242 invalid("a+Math.pow(++b, c)", "a+ ++b**c"),
243 invalid("(a)+(Math).pow((++b), c)", "(a)+ ++b**c"),
244 invalid("Math.pow(a, b)in c", "a**b in c"),
245 invalid("Math.pow(a, (b))in (c)", "a**b in (c)"),
246 invalid("a+Math.pow(++b, c)in d", "a+ ++b**c in d"),
247 invalid("a+Math.pow( ++b, c )in d", "a+ ++b**c in d"),
248
249 // tokens that cannot be adjacent, but there is already space or something else between
250 invalid("a+ Math.pow(++b, c) in d", "a+ ++b**c in d"),
251 invalid("a+/**/Math.pow(++b, c)/**/in d", "a+/**/++b**c/**/in d"),
252 invalid("a+(Math.pow(++b, c))in d", "a+(++b**c)in d"),
253
254 // tokens that cannot be adjacent, but the autofix inserts parens required for precedence, so there is no need for an extra space
255 invalid("+Math.pow(++a, b)", "+(++a**b)"),
256 invalid("Math.pow(a, b + c)in d", "a**(b + c)in d"),
257
258 {
259 code: "Math.pow(a, b) + Math.pow(c,\n d)",
260 output: "a**b + c**d",
261 errors: [
262 {
263 messageId: "useExponentiation",
264 type: "CallExpression",
265 line: 1,
266 column: 1,
267 endLine: 1,
268 endColumn: 15
269 },
270 {
271 messageId: "useExponentiation",
272 type: "CallExpression",
273 line: 1,
274 column: 18,
275 endLine: 2,
276 endColumn: 4
277 }
278 ]
279 },
280 {
281 code: "Math.pow(Math.pow(a, b), Math.pow(c, d))",
282 output: "Math.pow(a, b)**Math.pow(c, d)", // tests perform only one autofix iteration, below is the following one
283 errors: [
284 {
285 messageId: "useExponentiation",
286 type: "CallExpression",
287 column: 1,
288 endColumn: 41
289 },
290 {
291 messageId: "useExponentiation",
292 type: "CallExpression",
293 column: 10,
294 endColumn: 24
295 },
296 {
297 messageId: "useExponentiation",
298 type: "CallExpression",
299 column: 26,
300 endColumn: 40
301 }
302 ]
303 },
304 {
305 code: "Math.pow(a, b)**Math.pow(c, d)",
306 output: "(a**b)**c**d",
307 errors: [
308 {
309 messageId: "useExponentiation",
310 type: "CallExpression",
311 column: 1,
312 endColumn: 15
313 },
314 {
315 messageId: "useExponentiation",
316 type: "CallExpression",
317 column: 17,
318 endColumn: 31
319 }
320 ]
321 },
322
323 // shouldn't autofix if the call doesn't have exactly two arguments
324 invalid("Math.pow()", null),
325 invalid("Math.pow(a)", null),
326 invalid("Math.pow(a, b, c)", null),
327 invalid("Math.pow(a, b, c, d)", null),
328
329 // shouldn't autofix if any of the arguments is spread
330 invalid("Math.pow(...a)", null),
331 invalid("Math.pow(...a, b)", null),
332 invalid("Math.pow(a, ...b)", null),
333 invalid("Math.pow(a, b, ...c)", null),
334
335 // shouldn't autofix if that would remove comments
336 invalid("/* comment */Math.pow(a, b)", "/* comment */a**b"),
337 invalid("Math/**/.pow(a, b)", null),
338 invalid("Math//\n.pow(a, b)", null),
339 invalid("Math[//\n'pow'](a, b)", null),
340 invalid("Math['pow'/**/](a, b)", null),
341 invalid("Math./**/pow(a, b)", null),
342 invalid("Math.pow/**/(a, b)", null),
343 invalid("Math.pow//\n(a, b)", null),
344 invalid("Math.pow(/**/a, b)", null),
345 invalid("Math.pow(a,//\n b)", null),
346 invalid("Math.pow(a, b/**/)", null),
347 invalid("Math.pow(a, b//\n)", null),
348 invalid("Math.pow(a, b)/* comment */;", "a**b/* comment */;"),
349 invalid("Math.pow(a, b)// comment\n;", "a**b// comment\n;"),
350
351 // Optional chaining
352 invalid("Math.pow?.(a, b)", "a**b"),
353 invalid("Math?.pow(a, b)", "a**b"),
354 invalid("Math?.pow?.(a, b)", "a**b"),
355 invalid("(Math?.pow)(a, b)", "a**b"),
356 invalid("(Math?.pow)?.(a, b)", "a**b")
357 ]
358 });