]>
git.proxmox.com Git - pve-eslint.git/blob - eslint/tests/lib/rules/utils/ast-utils.js
c2a9201ac73dcedf0f835a1a2276c2d7ebab8b46
2 * @fileoverview Tests for ast utils.
3 * @author Gyandeep Singh
8 //------------------------------------------------------------------------------
10 //------------------------------------------------------------------------------
12 const assert
= require("chai").assert
,
13 util
= require("util"),
14 espree
= require("espree"),
15 astUtils
= require("../../../../lib/rules/utils/ast-utils"),
16 { Linter
} = require("../../../../lib/linter"),
17 { SourceCode
} = require("../../../../lib/source-code");
19 //------------------------------------------------------------------------------
21 //------------------------------------------------------------------------------
23 const ESPREE_CONFIG
= {
30 const linter
= new Linter();
32 describe("ast-utils", () => {
36 callCounts
= new Map();
40 * Asserts that a given function is called at least once during a test
41 * @param {Function} func The function that must be called at least once
42 * @returns {Function} A wrapper around the same function
44 function mustCall(func
) {
45 callCounts
.set(func
, 0);
46 return function Wrapper(...args
) {
47 callCounts
.set(func
, callCounts
.get(func
) + 1);
49 return func
.call(this, ...args
);
54 callCounts
.forEach((callCount
, func
) => {
57 `Expected ${func.toString()} to be called at least once but it was not called`
62 describe("isTokenOnSameLine", () => {
63 it("should return false if the tokens are not on the same line", () => {
64 linter
.defineRule("checker", {
65 create
: mustCall(context
=> ({
66 BlockStatement
: mustCall(node
=> {
67 assert
.isFalse(astUtils
.isTokenOnSameLine(context
.sourceCode
.getTokenBefore(node
), node
));
72 linter
.verify("if(a)\n{}", { rules
: { checker
: "error" } });
75 it("should return true if the tokens are on the same line", () => {
77 linter
.defineRule("checker", {
78 create
: mustCall(context
=> ({
79 BlockStatement
: mustCall(node
=> {
80 assert
.isTrue(astUtils
.isTokenOnSameLine(context
.sourceCode
.getTokenBefore(node
), node
));
85 linter
.verify("if(a){}", { rules
: { checker
: "error" } });
89 describe("isNullOrUndefined", () => {
90 it("should return true if the argument is null", () => {
91 assert
.isTrue(astUtils
.isNullOrUndefined(espree
.parse("null").body
[0].expression
));
94 it("should return true if the argument is undefined", () => {
95 assert
.isTrue(astUtils
.isNullOrUndefined(espree
.parse("undefined").body
[0].expression
));
98 it("should return false if the argument is a number", () => {
99 assert
.isFalse(astUtils
.isNullOrUndefined(espree
.parse("1").body
[0].expression
));
102 it("should return false if the argument is a string", () => {
103 assert
.isFalse(astUtils
.isNullOrUndefined(espree
.parse("'test'").body
[0].expression
));
106 it("should return false if the argument is a boolean", () => {
107 assert
.isFalse(astUtils
.isNullOrUndefined(espree
.parse("true").body
[0].expression
));
110 it("should return false if the argument is an object", () => {
111 assert
.isFalse(astUtils
.isNullOrUndefined(espree
.parse("({})").body
[0].expression
));
114 it("should return false if the argument is a unicode regex", () => {
115 assert
.isFalse(astUtils
.isNullOrUndefined(espree
.parse("/abc/u", { ecmaVersion
: 6 }).body
[0].expression
));
119 describe("checkReference", () => {
122 it("should return true if reference is assigned for catch", () => {
123 linter
.defineRule("checker", {
124 create
: mustCall(context
=> ({
125 CatchClause
: mustCall(node
=> {
126 const variables
= context
.sourceCode
.getDeclaredVariables(node
);
128 assert
.lengthOf(astUtils
.getModifyingReferences(variables
[0].references
), 1);
133 linter
.verify("try { } catch (e) { e = 10; }", { rules
: { checker
: "error" } });
137 it("should return true if reference is assigned for const", () => {
138 linter
.defineRule("checker", {
139 create
: mustCall(context
=> ({
140 VariableDeclaration
: mustCall(node
=> {
141 const variables
= context
.sourceCode
.getDeclaredVariables(node
);
143 assert
.lengthOf(astUtils
.getModifyingReferences(variables
[0].references
), 1);
148 linter
.verify("const a = 1; a = 2;", { rules
: { checker
: "error" }, parserOptions
: { ecmaVersion
: 6 } });
151 it("should return false if reference is not assigned for const", () => {
152 linter
.defineRule("checker", {
153 create
: mustCall(context
=> ({
154 VariableDeclaration
: mustCall(node
=> {
155 const variables
= context
.sourceCode
.getDeclaredVariables(node
);
157 assert
.lengthOf(astUtils
.getModifyingReferences(variables
[0].references
), 0);
162 linter
.verify("const a = 1; c = 2;", { rules
: { checker
: "error" }, parserOptions
: { ecmaVersion
: 6 } });
166 it("should return true if reference is assigned for class", () => {
167 linter
.defineRule("checker", {
168 create
: mustCall(context
=> ({
169 ClassDeclaration
: mustCall(node
=> {
170 const variables
= context
.sourceCode
.getDeclaredVariables(node
);
172 assert
.lengthOf(astUtils
.getModifyingReferences(variables
[0].references
), 1);
173 assert
.lengthOf(astUtils
.getModifyingReferences(variables
[1].references
), 0);
178 linter
.verify("class A { }\n A = 1;", { rules
: { checker
: "error" }, parserOptions
: { ecmaVersion
: 6 } });
181 it("should return false if reference is not assigned for class", () => {
182 linter
.defineRule("checker", {
183 create
: mustCall(context
=> ({
184 ClassDeclaration
: mustCall(node
=> {
185 const variables
= context
.sourceCode
.getDeclaredVariables(node
);
187 assert
.lengthOf(astUtils
.getModifyingReferences(variables
[0].references
), 0);
192 linter
.verify("class A { } foo(A);", { rules
: { checker
: "error" }, parserOptions
: { ecmaVersion
: 6 } });
196 describe("isDirectiveComment", () => {
199 * Asserts the node is NOT a directive comment
200 * @param {ASTNode} node node to assert
203 function assertFalse(node
) {
204 assert
.isFalse(astUtils
.isDirectiveComment(node
));
208 * Asserts the node is a directive comment
209 * @param {ASTNode} node node to assert
212 function assertTrue(node
) {
213 assert
.isTrue(astUtils
.isDirectiveComment(node
));
216 it("should return false if it is not a directive line comment", () => {
218 "// lalala I'm a normal comment",
219 "// trying to confuse eslint ",
220 "//trying to confuse eslint-directive-detection",
221 "//eslint is awesome",
222 "//global line comment is not a directive",
223 "//globals line comment is not a directive",
224 "//exported line comment is not a directive"
226 const ast
= espree
.parse(code
, ESPREE_CONFIG
);
227 const sourceCode
= new SourceCode(code
, ast
);
228 const comments
= sourceCode
.getAllComments();
230 comments
.forEach(assertFalse
);
233 it("should return false if it is not a directive block comment", () => {
235 "/* lalala I'm a normal comment */",
236 "/* trying to confuse eslint */",
237 "/* trying to confuse eslint-directive-detection */",
238 "/*eSlInT is awesome*/"
240 const ast
= espree
.parse(code
, ESPREE_CONFIG
);
241 const sourceCode
= new SourceCode(code
, ast
);
242 const comments
= sourceCode
.getAllComments();
244 comments
.forEach(assertFalse
);
247 it("should return true if it is a directive line comment", () => {
249 "// eslint-disable-line no-undef",
250 "// eslint-secret-directive 4 8 15 16 23 42 ",
251 "// eslint-directive-without-argument",
252 "//eslint-directive-without-padding"
254 const ast
= espree
.parse(code
, ESPREE_CONFIG
);
255 const sourceCode
= new SourceCode(code
, ast
);
256 const comments
= sourceCode
.getAllComments();
258 comments
.forEach(assertTrue
);
261 it("should return true if it is a directive block comment", () => {
263 "/* eslint-disable no-undef */",
264 "/*eslint-enable no-undef*/",
265 "/* eslint-env {\"es6\": true} */",
272 const ast
= espree
.parse(code
, ESPREE_CONFIG
);
273 const sourceCode
= new SourceCode(code
, ast
);
274 const comments
= sourceCode
.getAllComments();
276 comments
.forEach(assertTrue
);
280 describe("isParenthesised", () => {
281 it("should return false for not parenthesised nodes", () => {
282 const code
= "condition ? 1 : 2";
283 const ast
= espree
.parse(code
, ESPREE_CONFIG
);
284 const sourceCode
= new SourceCode(code
, ast
);
286 assert
.isFalse(astUtils
.isParenthesised(sourceCode
, ast
.body
[0].expression
));
289 it("should return true for not parenthesised nodes", () => {
290 const code
= "(condition ? 1 : 2)";
291 const ast
= espree
.parse(code
, ESPREE_CONFIG
);
292 const sourceCode
= new SourceCode(code
, ast
);
294 assert
.isTrue(astUtils
.isParenthesised(sourceCode
, ast
.body
[0].expression
));
298 describe("isFunction", () => {
299 it("should return true for FunctionDeclaration", () => {
300 const ast
= espree
.parse("function a() {}");
301 const node
= ast
.body
[0];
303 assert(astUtils
.isFunction(node
));
306 it("should return true for FunctionExpression", () => {
307 const ast
= espree
.parse("(function a() {})");
308 const node
= ast
.body
[0].expression
;
310 assert(astUtils
.isFunction(node
));
313 it("should return true for AllowFunctionExpression", () => {
314 const ast
= espree
.parse("(() => {})", { ecmaVersion
: 6 });
315 const node
= ast
.body
[0].expression
;
317 assert(astUtils
.isFunction(node
));
320 it("should return false for Program, VariableDeclaration, BlockStatement", () => {
321 const ast
= espree
.parse("var a; { }");
323 assert(!astUtils
.isFunction(ast
));
324 assert(!astUtils
.isFunction(ast
.body
[0]));
325 assert(!astUtils
.isFunction(ast
.body
[1]));
329 describe("isLoop", () => {
330 it("should return true for DoWhileStatement", () => {
331 const ast
= espree
.parse("do {} while (a)");
332 const node
= ast
.body
[0];
334 assert(astUtils
.isLoop(node
));
337 it("should return true for ForInStatement", () => {
338 const ast
= espree
.parse("for (var k in obj) {}");
339 const node
= ast
.body
[0];
341 assert(astUtils
.isLoop(node
));
344 it("should return true for ForOfStatement", () => {
345 const ast
= espree
.parse("for (var x of list) {}", { ecmaVersion
: 6 });
346 const node
= ast
.body
[0];
348 assert(astUtils
.isLoop(node
));
351 it("should return true for ForStatement", () => {
352 const ast
= espree
.parse("for (var i = 0; i < 10; ++i) {}");
353 const node
= ast
.body
[0];
355 assert(astUtils
.isLoop(node
));
358 it("should return true for WhileStatement", () => {
359 const ast
= espree
.parse("while (a) {}");
360 const node
= ast
.body
[0];
362 assert(astUtils
.isLoop(node
));
365 it("should return false for Program, VariableDeclaration, BlockStatement", () => {
366 const ast
= espree
.parse("var a; { }");
368 assert(!astUtils
.isLoop(ast
));
369 assert(!astUtils
.isLoop(ast
.body
[0]));
370 assert(!astUtils
.isLoop(ast
.body
[1]));
374 describe("isInLoop", () => {
377 * Asserts that the unique node of the given type in the code is either
378 * in a loop or not in a loop.
379 * @param {string} code the code to check.
380 * @param {string} nodeType the type of the node to consider. The code
381 * must have exactly one node of ths type.
382 * @param {boolean} expectedInLoop the expected result for whether the
386 function assertNodeTypeInLoop(code
, nodeType
, expectedInLoop
) {
389 linter
.defineRule("checker", {
390 create
: mustCall(() => ({
391 [nodeType
]: mustCall(node
=> {
392 results
.push(astUtils
.isInLoop(node
));
396 linter
.verify(code
, { rules
: { checker
: "error" }, parserOptions
: { ecmaVersion
: 6 } });
398 assert
.lengthOf(results
, 1);
399 assert
.strictEqual(results
[0], expectedInLoop
);
402 it("should return true for a loop itself", () => {
403 assertNodeTypeInLoop("while (a) {}", "WhileStatement", true);
406 it("should return true for a loop condition", () => {
407 assertNodeTypeInLoop("while (a) {}", "Identifier", true);
410 it("should return true for a loop assignee", () => {
411 assertNodeTypeInLoop("for (var a in b) {}", "VariableDeclaration", true);
414 it("should return true for a node within a loop body", () => {
415 assertNodeTypeInLoop("for (var a of b) { console.log('Hello'); }", "Literal", true);
418 it("should return false for a node outside a loop body", () => {
419 assertNodeTypeInLoop("while (true) {} a(b);", "CallExpression", false);
422 it("should return false when the loop is not in the current function", () => {
423 assertNodeTypeInLoop("while (true) { funcs.push(() => { var a; }); }", "VariableDeclaration", false);
427 describe("getStaticStringValue", () => {
429 /* eslint-disable quote-props -- Make consistent here for readability */
430 const expectedResults
= {
456 "12.34e5": "1234000",
457 "12.34e-5": "0.0001234",
470 "/[0-9]/": "/[0-9]/",
471 "/(?<zero>0)/": "/(?<zero>0)/",
472 "/(?<zero>0)/s": "/(?<zero>0)/s",
473 "/(?<=a)b/s": "/(?<=a)b/s",
475 // simple template literals
491 "(function () {})": null
493 /* eslint-enable quote-props -- Make consistent here for readability */
495 Object
.keys(expectedResults
).forEach(key
=> {
496 it(`should return ${expectedResults[key]} for ${key}`, () => {
497 const ast
= espree
.parse(key
, { ecmaVersion
: 2018 });
499 assert
.strictEqual(astUtils
.getStaticStringValue(ast
.body
[0].expression
), expectedResults
[key
]);
503 it("should return text of regex literal even if it's not supported natively.", () => {
507 regex
: { pattern
: "(?:)", flags
: "u" }
509 const expectedText
= "/(?:)/u";
511 assert
.strictEqual(astUtils
.getStaticStringValue(node
), expectedText
);
514 it("should return text of bigint literal even if it's not supported natively.", () => {
520 const expectedText
= "100n";
522 assert
.strictEqual(astUtils
.getStaticStringValue(node
), expectedText
);
526 describe("getStaticPropertyName", () => {
527 it("should return 'b' for `a.b`", () => {
528 const ast
= espree
.parse("a.b");
529 const node
= ast
.body
[0].expression
;
531 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), "b");
534 it("should return 'b' for `a['b']`", () => {
535 const ast
= espree
.parse("a['b']");
536 const node
= ast
.body
[0].expression
;
538 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), "b");
541 it("should return 'b' for `a[`b`]`", () => {
542 const ast
= espree
.parse("a[`b`]", { ecmaVersion
: 6 });
543 const node
= ast
.body
[0].expression
;
545 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), "b");
548 it("should return '100' for `a[100]`", () => {
549 const ast
= espree
.parse("a[100]");
550 const node
= ast
.body
[0].expression
;
552 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), "100");
555 it("should return null for `a[b]`", () => {
556 const ast
= espree
.parse("a[b]");
557 const node
= ast
.body
[0].expression
;
559 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), null);
562 it("should return null for `a['a' + 'b']`", () => {
563 const ast
= espree
.parse("a['a' + 'b']");
564 const node
= ast
.body
[0].expression
;
566 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), null);
569 it("should return null for `a[tag`b`]`", () => {
570 const ast
= espree
.parse("a[tag`b`]", { ecmaVersion
: 6 });
571 const node
= ast
.body
[0].expression
;
573 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), null);
576 it("should return null for `a[`${b}`]`", () => {
577 const ast
= espree
.parse("a[`${b}`]", { ecmaVersion
: 6 });
578 const node
= ast
.body
[0].expression
;
580 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), null);
583 it("should return 'b' for `b: 1`", () => {
584 const ast
= espree
.parse("({b: 1})");
585 const node
= ast
.body
[0].expression
.properties
[0];
587 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), "b");
590 it("should return 'b' for `b() {}`", () => {
591 const ast
= espree
.parse("({b() {}})", { ecmaVersion
: 6 });
592 const node
= ast
.body
[0].expression
.properties
[0];
594 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), "b");
597 it("should return 'b' for `get b() {}`", () => {
598 const ast
= espree
.parse("({get b() {}})", { ecmaVersion
: 6 });
599 const node
= ast
.body
[0].expression
.properties
[0];
601 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), "b");
604 it("should return 'b' for `['b']: 1`", () => {
605 const ast
= espree
.parse("({['b']: 1})", { ecmaVersion
: 6 });
606 const node
= ast
.body
[0].expression
.properties
[0];
608 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), "b");
611 it("should return 'b' for `['b']() {}`", () => {
612 const ast
= espree
.parse("({['b']() {}})", { ecmaVersion
: 6 });
613 const node
= ast
.body
[0].expression
.properties
[0];
615 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), "b");
618 it("should return 'b' for `[`b`]: 1`", () => {
619 const ast
= espree
.parse("({[`b`]: 1})", { ecmaVersion
: 6 });
620 const node
= ast
.body
[0].expression
.properties
[0];
622 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), "b");
625 it("should return '100' for` [100]: 1`", () => {
626 const ast
= espree
.parse("({[100]: 1})", { ecmaVersion
: 6 });
627 const node
= ast
.body
[0].expression
.properties
[0];
629 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), "100");
632 it("should return '/(?<zero>0)/' for `[/(?<zero>0)/]: 1`", () => {
633 const ast
= espree
.parse("({[/(?<zero>0)/]: 1})", { ecmaVersion
: 2018 });
634 const node
= ast
.body
[0].expression
.properties
[0];
636 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), "/(?<zero>0)/");
639 it("should return null for `[b]: 1`", () => {
640 const ast
= espree
.parse("({[b]: 1})", { ecmaVersion
: 6 });
641 const node
= ast
.body
[0].expression
.properties
[0];
643 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), null);
646 it("should return null for `['a' + 'b']: 1`", () => {
647 const ast
= espree
.parse("({['a' + 'b']: 1})", { ecmaVersion
: 6 });
648 const node
= ast
.body
[0].expression
.properties
[0];
650 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), null);
653 it("should return null for `[tag`b`]: 1`", () => {
654 const ast
= espree
.parse("({[tag`b`]: 1})", { ecmaVersion
: 6 });
655 const node
= ast
.body
[0].expression
.properties
[0];
657 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), null);
660 it("should return null for `[`${b}`]: 1`", () => {
661 const ast
= espree
.parse("({[`${b}`]: 1})", { ecmaVersion
: 6 });
662 const node
= ast
.body
[0].expression
.properties
[0];
664 assert
.strictEqual(astUtils
.getStaticPropertyName(node
), null);
667 it("should return null for non member expressions", () => {
668 const ast
= espree
.parse("foo()");
670 assert
.strictEqual(astUtils
.getStaticPropertyName(ast
.body
[0].expression
), null);
671 assert
.strictEqual(astUtils
.getStaticPropertyName(ast
.body
[0]), null);
672 assert
.strictEqual(astUtils
.getStaticPropertyName(ast
.body
), null);
673 assert
.strictEqual(astUtils
.getStaticPropertyName(ast
), null);
674 assert
.strictEqual(astUtils
.getStaticPropertyName(null), null);
678 describe("getDirectivePrologue", () => {
679 it("should return empty array if node is not a Program, FunctionDeclaration, FunctionExpression, or ArrowFunctionExpression", () => {
680 const ast
= espree
.parse("if (a) { b(); }");
681 const node
= ast
.body
[0];
683 assert
.deepStrictEqual(astUtils
.getDirectivePrologue(node
), []);
686 it("should return empty array if node is a braceless ArrowFunctionExpression node", () => {
687 const ast
= espree
.parse("var foo = () => 'use strict';", { ecmaVersion
: 6 });
688 const node
= ast
.body
[0].declarations
[0].init
;
690 assert
.deepStrictEqual(astUtils
.getDirectivePrologue(node
), []);
693 it("should return empty array if there are no directives in Program body", () => {
694 const ast
= espree
.parse("var foo;");
697 assert
.deepStrictEqual(astUtils
.getDirectivePrologue(node
), []);
700 it("should return empty array if there are no directives in FunctionDeclaration body", () => {
701 const ast
= espree
.parse("function foo() { return bar; }");
702 const node
= ast
.body
[0];
704 assert
.deepStrictEqual(astUtils
.getDirectivePrologue(node
), []);
707 it("should return empty array if there are no directives in FunctionExpression body", () => {
708 const ast
= espree
.parse("var foo = function() { return bar; }");
709 const node
= ast
.body
[0].declarations
[0].init
;
711 assert
.deepStrictEqual(astUtils
.getDirectivePrologue(node
), []);
714 it("should return empty array if there are no directives in ArrowFunctionExpression body", () => {
715 const ast
= espree
.parse("var foo = () => { return bar; };", { ecmaVersion
: 6 });
716 const node
= ast
.body
[0].declarations
[0].init
;
718 assert
.deepStrictEqual(astUtils
.getDirectivePrologue(node
), []);
721 it("should return directives in Program body", () => {
722 const ast
= espree
.parse("'use strict'; 'use asm'; var foo;");
723 const result
= astUtils
.getDirectivePrologue(ast
);
725 assert
.strictEqual(result
.length
, 2);
726 assert
.strictEqual(result
[0].expression
.value
, "use strict");
727 assert
.strictEqual(result
[1].expression
.value
, "use asm");
730 it("should return directives in FunctionDeclaration body", () => {
731 const ast
= espree
.parse("function foo() { 'use strict'; 'use asm'; return bar; }");
732 const result
= astUtils
.getDirectivePrologue(ast
.body
[0]);
734 assert
.strictEqual(result
.length
, 2);
735 assert
.strictEqual(result
[0].expression
.value
, "use strict");
736 assert
.strictEqual(result
[1].expression
.value
, "use asm");
739 it("should return directives in FunctionExpression body", () => {
740 const ast
= espree
.parse("var foo = function() { 'use strict'; 'use asm'; return bar; }");
741 const result
= astUtils
.getDirectivePrologue(ast
.body
[0].declarations
[0].init
);
743 assert
.strictEqual(result
.length
, 2);
744 assert
.strictEqual(result
[0].expression
.value
, "use strict");
745 assert
.strictEqual(result
[1].expression
.value
, "use asm");
748 it("should return directives in ArrowFunctionExpression body", () => {
749 const ast
= espree
.parse("var foo = () => { 'use strict'; 'use asm'; return bar; };", { ecmaVersion
: 6 });
750 const result
= astUtils
.getDirectivePrologue(ast
.body
[0].declarations
[0].init
);
752 assert
.strictEqual(result
.length
, 2);
753 assert
.strictEqual(result
[0].expression
.value
, "use strict");
754 assert
.strictEqual(result
[1].expression
.value
, "use asm");
759 const expectedResults
= {
776 "1_23_4_56_7_89": true,
820 "1_2.3_4e5_6": false,
827 const ecmaVersion
= espree
.latestEcmaVersion
;
829 describe("isDecimalInteger", () => {
830 Object
.keys(expectedResults
).forEach(key
=> {
831 it(`should return ${expectedResults[key]} for ${key}`, () => {
833 astUtils
.isDecimalInteger(
834 espree
.parse(key
, { ecmaVersion
}).body
[0].expression
842 describe("isDecimalIntegerNumericToken", () => {
843 Object
.keys(expectedResults
).forEach(key
=> {
844 it(`should return ${expectedResults[key]} for ${key}`, () => {
846 astUtils
.isDecimalIntegerNumericToken(
847 espree
.tokenize(key
, { ecmaVersion
})[0]
856 describe("getFunctionNameWithKind", () => {
857 const expectedResults
= {
858 "function foo() {}": "function 'foo'",
859 "(function foo() {})": "function 'foo'",
860 "(function() {})": "function",
861 "function* foo() {}": "generator function 'foo'",
862 "(function* foo() {})": "generator function 'foo'",
863 "(function*() {})": "generator function",
864 "() => {}": "arrow function",
865 "async () => {}": "async arrow function",
866 "({ foo: function foo() {} })": "method 'foo'",
867 "({ foo: function() {} })": "method 'foo'",
868 "({ '': function() {} })": "method ''",
869 "({ ['foo']: function() {} })": "method 'foo'",
870 "({ ['']: function() {} })": "method ''",
871 "({ [foo]: function() {} })": "method",
872 "({ foo() {} })": "method 'foo'",
873 "({ foo: function* foo() {} })": "generator method 'foo'",
874 "({ foo: function*() {} })": "generator method 'foo'",
875 "({ ['foo']: function*() {} })": "generator method 'foo'",
876 "({ [foo]: function*() {} })": "generator method",
877 "({ *foo() {} })": "generator method 'foo'",
878 "({ foo: async function foo() {} })": "async method 'foo'",
879 "({ foo: async function() {} })": "async method 'foo'",
880 "({ ['foo']: async function() {} })": "async method 'foo'",
881 "({ [foo]: async function() {} })": "async method",
882 "({ async foo() {} })": "async method 'foo'",
883 "({ get foo() {} })": "getter 'foo'",
884 "({ set foo(a) {} })": "setter 'foo'",
885 "class A { constructor() {} }": "constructor",
886 "class A { foo() {} }": "method 'foo'",
887 "class A { *foo() {} }": "generator method 'foo'",
888 "class A { async foo() {} }": "async method 'foo'",
889 "class A { ['foo']() {} }": "method 'foo'",
890 "class A { *['foo']() {} }": "generator method 'foo'",
891 "class A { async ['foo']() {} }": "async method 'foo'",
892 "class A { [foo]() {} }": "method",
893 "class A { *[foo]() {} }": "generator method",
894 "class A { async [foo]() {} }": "async method",
895 "class A { get foo() {} }": "getter 'foo'",
896 "class A { set foo(a) {} }": "setter 'foo'",
897 "class A { static foo() {} }": "static method 'foo'",
898 "class A { static *foo() {} }": "static generator method 'foo'",
899 "class A { static async foo() {} }": "static async method 'foo'",
900 "class A { static get foo() {} }": "static getter 'foo'",
901 "class A { static set foo(a) {} }": "static setter 'foo'",
902 "class A { foo = () => {}; }": "method 'foo'",
903 "class A { foo = function() {}; }": "method 'foo'",
904 "class A { foo = function bar() {}; }": "method 'foo'",
905 "class A { static foo = () => {}; }": "static method 'foo'",
906 "class A { '#foo' = () => {}; }": "method '#foo'",
907 "class A { #foo = () => {}; }": "private method #foo",
908 "class A { static #foo = () => {}; }": "static private method #foo",
909 "class A { '#foo'() {} }": "method '#foo'",
910 "class A { #foo() {} }": "private method #foo",
911 "class A { static #foo() {} }": "static private method #foo"
914 Object
.keys(expectedResults
).forEach(key
=> {
915 it(`should return "${expectedResults[key]}" for "${key}".`, () => {
916 linter
.defineRule("checker", {
917 create
: mustCall(() => ({
918 ":function": mustCall(node
=> {
920 astUtils
.getFunctionNameWithKind(node
),
927 linter
.verify(key
, { rules
: { checker
: "error" }, parserOptions
: { ecmaVersion
: 13 } });
932 describe("getFunctionHeadLoc", () => {
933 const expectedResults
= {
934 "function foo() {}": [0, 12],
935 "(function foo() {})": [1, 13],
936 "(function() {})": [1, 9],
937 "function* foo() {}": [0, 13],
938 "(function* foo() {})": [1, 14],
939 "(function*() {})": [1, 10],
941 "async () => {}": [9, 11],
942 "({ foo: function foo() {} })": [3, 20],
943 "({ foo: function() {} })": [3, 16],
944 "({ ['foo']: function() {} })": [3, 20],
945 "({ [foo]: function() {} })": [3, 18],
946 "({ foo() {} })": [3, 6],
947 "({ foo: function* foo() {} })": [3, 21],
948 "({ foo: function*() {} })": [3, 17],
949 "({ ['foo']: function*() {} })": [3, 21],
950 "({ [foo]: function*() {} })": [3, 19],
951 "({ *foo() {} })": [3, 7],
952 "({ foo: async function foo() {} })": [3, 26],
953 "({ foo: async function() {} })": [3, 22],
954 "({ ['foo']: async function() {} })": [3, 26],
955 "({ [foo]: async function() {} })": [3, 24],
956 "({ async foo() {} })": [3, 12],
957 "({ get foo() {} })": [3, 10],
958 "({ set foo(a) {} })": [3, 10],
959 "class A { constructor() {} }": [10, 21],
960 "class A { foo() {} }": [10, 13],
961 "class A { *foo() {} }": [10, 14],
962 "class A { async foo() {} }": [10, 19],
963 "class A { ['foo']() {} }": [10, 17],
964 "class A { *['foo']() {} }": [10, 18],
965 "class A { async ['foo']() {} }": [10, 23],
966 "class A { [foo]() {} }": [10, 15],
967 "class A { *[foo]() {} }": [10, 16],
968 "class A { async [foo]() {} }": [10, 21],
969 "class A { get foo() {} }": [10, 17],
970 "class A { set foo(a) {} }": [10, 17],
971 "class A { static foo() {} }": [10, 20],
972 "class A { static *foo() {} }": [10, 21],
973 "class A { static async foo() {} }": [10, 26],
974 "class A { static get foo() {} }": [10, 24],
975 "class A { static set foo(a) {} }": [10, 24],
976 "class A { foo = function() {}; }": [10, 24],
977 "class A { foo = function bar() {}; }": [10, 28],
978 "class A { static foo = function() {}; }": [10, 31],
979 "class A { foo = () => {}; }": [10, 16],
980 "class A { foo = arg => {}; }": [10, 16]
983 Object
.keys(expectedResults
).forEach(key
=> {
984 const expectedLoc
= {
987 column
: expectedResults
[key
][0]
991 column
: expectedResults
[key
][1]
995 it(`should return "${JSON.stringify(expectedLoc)}" for "${key}".`, () => {
996 linter
.defineRule("checker", {
997 create
: mustCall(() => ({
998 ":function": mustCall(node
=> {
999 assert
.deepStrictEqual(
1000 astUtils
.getFunctionHeadLoc(node
, linter
.getSourceCode()),
1007 linter
.verify(key
, { rules
: { checker
: "error" }, parserOptions
: { ecmaVersion
: 13 } }, "test.js", true);
1012 describe("isEmptyBlock", () => {
1013 const expectedResults
= {
1019 Object
.keys(expectedResults
).forEach(key
=> {
1020 it(`should return ${expectedResults[key]} for ${key}`, () => {
1021 const ast
= espree
.parse(key
);
1023 assert
.strictEqual(astUtils
.isEmptyBlock(ast
.body
[0]), expectedResults
[key
]);
1028 describe("isEmptyFunction", () => {
1029 const expectedResults
= {
1030 "(function foo() {})": true,
1031 "(function foo() { a })": false,
1033 "(a) => { a }": false,
1037 Object
.keys(expectedResults
).forEach(key
=> {
1038 it(`should return ${expectedResults[key]} for ${key}`, () => {
1039 const ast
= espree
.parse(key
, { ecmaVersion
: 6 });
1041 assert
.strictEqual(astUtils
.isEmptyFunction(ast
.body
[0].expression
), expectedResults
[key
]);
1046 describe("getNextLocation", () => {
1048 /* eslint-disable quote-props -- Make consistent here for readability */
1049 const expectedResults
= {
1051 "\n": [[1, 0], [2, 0], null],
1052 "\r\n": [[1, 0], [2, 0], null],
1053 "foo": [[1, 0], [1, 1], [1, 2], [1, 3], null],
1054 "foo\n": [[1, 0], [1, 1], [1, 2], [1, 3], [2, 0], null],
1055 "foo\r\n": [[1, 0], [1, 1], [1, 2], [1, 3], [2, 0], null],
1056 "foo;\n": [[1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [2, 0], null],
1057 "a\nb": [[1, 0], [1, 1], [2, 0], [2, 1], null],
1058 "a\nb\n": [[1, 0], [1, 1], [2, 0], [2, 1], [3, 0], null],
1059 "a\r\nb\r\n": [[1, 0], [1, 1], [2, 0], [2, 1], [3, 0], null],
1060 "a\nb\r\n": [[1, 0], [1, 1], [2, 0], [2, 1], [3, 0], null],
1061 "a\n\n": [[1, 0], [1, 1], [2, 0], [3, 0], null],
1062 "a\r\n\r\n": [[1, 0], [1, 1], [2, 0], [3, 0], null],
1063 "\n\r\n\n\r\n": [[1, 0], [2, 0], [3, 0], [4, 0], [5, 0], null],
1064 "ab\u2029c": [[1, 0], [1, 1], [1, 2], [2, 0], [2, 1], null],
1065 "ab\ncde\n": [[1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2], [2, 3], [3, 0], null],
1066 "a ": [[1, 0], [1, 1], [1, 2], null],
1067 "a\t": [[1, 0], [1, 1], [1, 2], null],
1068 "a \n": [[1, 0], [1, 1], [1, 2], [2, 0], null]
1070 /* eslint-enable quote-props -- Make consistent here for readability */
1072 Object
.keys(expectedResults
).forEach(code
=> {
1073 it(`should return expected locations for "${code}".`, () => {
1074 const ast
= espree
.parse(code
, ESPREE_CONFIG
);
1075 const sourceCode
= new SourceCode(code
, ast
);
1076 const locations
= expectedResults
[code
];
1078 for (let i
= 0; i
< locations
.length
- 1; i
++) {
1079 const location
= { line
: locations
[i
][0], column
: locations
[i
][1] };
1080 const expectedNextLocation
= locations
[i
+ 1]
1081 ? { line
: locations
[i
+ 1][0], column
: locations
[i
+ 1][1] }
1084 assert
.deepStrictEqual(
1085 astUtils
.getNextLocation(sourceCode
, location
),
1086 expectedNextLocation
1093 describe("getParenthesisedText", () => {
1094 const expectedResults
= {
1095 "(((foo))); bar;": "(((foo)))",
1096 "(/* comment */(((foo.bar())))); baz();": "(/* comment */(((foo.bar()))))",
1097 "(foo, bar)": "(foo, bar)"
1100 Object
.keys(expectedResults
).forEach(key
=> {
1101 it(`should return ${expectedResults[key]} for ${key}`, () => {
1102 const ast
= espree
.parse(key
, { tokens
: true, comment
: true, range
: true, loc
: true });
1103 const sourceCode
= new SourceCode(key
, ast
);
1105 assert
.strictEqual(astUtils
.getParenthesisedText(sourceCode
, ast
.body
[0].expression
), expectedResults
[key
]);
1110 describe("couldBeError", () => {
1111 const EXPECTED_RESULTS
= {
1122 "(foo = bar)": true,
1124 "(foo += bar)": false,
1125 "(foo -= bar)": false,
1126 "(foo *= bar)": false,
1127 "(foo /= bar)": false,
1128 "(foo %= bar)": false,
1129 "(foo **= bar)": false,
1130 "(foo <<= bar)": false,
1131 "(foo >>= bar)": false,
1132 "(foo >>>= bar)": false,
1133 "(foo &= bar)": false,
1134 "(foo |= bar)": false,
1135 "(foo ^= bar)": false,
1137 "(foo, 2, 3)": false,
1138 "(1, 2, foo)": true,
1143 // A future improvement could detect the left side as statically falsy, making this false.
1144 "false && foo": true,
1146 "foo.bar ??= 2": true,
1147 "foo[bar] ||= 2": true,
1148 "foo ? 1 : 2": false,
1149 "foo ? bar : 2": true,
1150 "foo ? 1 : bar": true,
1152 "({ foo: 1 })": false
1155 Object
.keys(EXPECTED_RESULTS
).forEach(key
=> {
1156 it(`returns ${EXPECTED_RESULTS[key]} for ${key}`, () => {
1157 const ast
= espree
.parse(key
, { ecmaVersion
: 2021 });
1159 assert
.strictEqual(astUtils
.couldBeError(ast
.body
[0].expression
), EXPECTED_RESULTS
[key
]);
1164 describe("isArrowToken", () => {
1165 const code
= "() => 5";
1166 const tokens
= espree
.parse(code
, { ecmaVersion
: 6, tokens
: true }).tokens
;
1167 const expected
= [false, false, true, false];
1169 tokens
.forEach((token
, index
) => {
1170 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1171 assert
.strictEqual(astUtils
.isArrowToken(token
), expected
[index
]);
1177 const code
= "if (obj && foo) { obj[foo](); }";
1178 const tokens
= espree
.parse(code
, { ecmaVersion
: 6, tokens
: true }).tokens
;
1179 const expected
= [false, false, false, false, false, false, false, false, false, false, false, false, false, false, true];
1181 describe("isClosingBraceToken", () => {
1182 tokens
.forEach((token
, index
) => {
1183 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1184 assert
.strictEqual(astUtils
.isClosingBraceToken(token
), expected
[index
]);
1189 describe("isNotClosingBraceToken", () => {
1190 tokens
.forEach((token
, index
) => {
1191 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1192 assert
.strictEqual(astUtils
.isNotClosingBraceToken(token
), !expected
[index
]);
1199 const code
= "if (obj && foo) { obj[foo](); }";
1200 const tokens
= espree
.parse(code
, { ecmaVersion
: 6, tokens
: true }).tokens
;
1201 const expected
= [false, false, false, false, false, false, false, false, false, false, true, false, false, false, false];
1203 describe("isClosingBracketToken", () => {
1204 tokens
.forEach((token
, index
) => {
1205 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1206 assert
.strictEqual(astUtils
.isClosingBracketToken(token
), expected
[index
]);
1211 describe("isNotClosingBracketToken", () => {
1212 tokens
.forEach((token
, index
) => {
1213 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1214 assert
.strictEqual(astUtils
.isNotClosingBracketToken(token
), !expected
[index
]);
1221 const code
= "if (obj && foo) { obj[foo](); }";
1222 const tokens
= espree
.parse(code
, { ecmaVersion
: 6, tokens
: true }).tokens
;
1223 const expected
= [false, false, false, false, false, true, false, false, false, false, false, false, true, false, false];
1225 describe("isClosingParenToken", () => {
1226 tokens
.forEach((token
, index
) => {
1227 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1228 assert
.strictEqual(astUtils
.isClosingParenToken(token
), expected
[index
]);
1233 describe("isNotClosingParenToken", () => {
1234 tokens
.forEach((token
, index
) => {
1235 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1236 assert
.strictEqual(astUtils
.isNotClosingParenToken(token
), !expected
[index
]);
1243 const code
= "const obj = {foo: 1, bar: 2};";
1244 const tokens
= espree
.parse(code
, { ecmaVersion
: 6, tokens
: true }).tokens
;
1245 const expected
= [false, false, false, false, false, true, false, false, false, true, false, false, false];
1247 describe("isColonToken", () => {
1248 tokens
.forEach((token
, index
) => {
1249 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1250 assert
.strictEqual(astUtils
.isColonToken(token
), expected
[index
]);
1255 describe("isNotColonToken", () => {
1256 tokens
.forEach((token
, index
) => {
1257 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1258 assert
.strictEqual(astUtils
.isNotColonToken(token
), !expected
[index
]);
1265 const code
= "const obj = {foo: 1, bar: 2};";
1266 const tokens
= espree
.parse(code
, { ecmaVersion
: 6, tokens
: true }).tokens
;
1267 const expected
= [false, false, false, false, false, false, false, true, false, false, false, false, false];
1269 describe("isCommaToken", () => {
1270 tokens
.forEach((token
, index
) => {
1271 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1272 assert
.strictEqual(astUtils
.isCommaToken(token
), expected
[index
]);
1277 describe("isNotCommaToken", () => {
1278 tokens
.forEach((token
, index
) => {
1279 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1280 assert
.strictEqual(astUtils
.isNotCommaToken(token
), !expected
[index
]);
1287 const code
= "const obj = {foo: 1.5, bar: a.b};";
1288 const tokens
= espree
.parse(code
, { ecmaVersion
: 6, tokens
: true }).tokens
;
1289 const expected
= [false, false, false, false, false, false, false, false, false, false, false, true, false, false, false];
1291 describe("isDotToken", () => {
1292 tokens
.forEach((token
, index
) => {
1293 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1294 assert
.strictEqual(astUtils
.isDotToken(token
), expected
[index
]);
1299 describe("isNotDotToken", () => {
1300 tokens
.forEach((token
, index
) => {
1301 it(`should return ${!expected[index]} for '${token.value}'.`, () => {
1302 assert
.strictEqual(astUtils
.isNotDotToken(token
), !expected
[index
]);
1308 describe("isCommentToken", () => {
1309 const code
= "const obj = /*block*/ {foo: 1, bar: 2}; //line";
1310 const ast
= espree
.parse(code
, { ecmaVersion
: 6, tokens
: true, comment
: true });
1312 ast
.tokens
.forEach(token
=> {
1313 it(`should return false for '${token.value}'.`, () => {
1314 assert
.strictEqual(astUtils
.isCommentToken(token
), false);
1317 ast
.comments
.forEach(comment
=> {
1318 it(`should return true for '${comment.value}'.`, () => {
1319 assert
.strictEqual(astUtils
.isCommentToken(comment
), true);
1324 describe("isKeywordToken", () => {
1325 const code
= "const obj = {foo: 1, bar: 2};";
1326 const tokens
= espree
.parse(code
, { ecmaVersion
: 6, tokens
: true }).tokens
;
1327 const expected
= [true, false, false, false, false, false, false, false, false, false, false, false, false];
1329 tokens
.forEach((token
, index
) => {
1330 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1331 assert
.strictEqual(astUtils
.isKeywordToken(token
), expected
[index
]);
1337 const code
= "if (obj && foo) { obj[foo](); }";
1338 const tokens
= espree
.parse(code
, { ecmaVersion
: 6, tokens
: true }).tokens
;
1339 const expected
= [false, false, false, false, false, false, true, false, false, false, false, false, false, false, false];
1341 describe("isOpeningBraceToken", () => {
1342 tokens
.forEach((token
, index
) => {
1343 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1344 assert
.strictEqual(astUtils
.isOpeningBraceToken(token
), expected
[index
]);
1349 describe("isNotOpeningBraceToken", () => {
1350 tokens
.forEach((token
, index
) => {
1351 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1352 assert
.strictEqual(astUtils
.isNotOpeningBraceToken(token
), !expected
[index
]);
1359 const code
= "if (obj && foo) { obj[foo](); }";
1360 const tokens
= espree
.parse(code
, { ecmaVersion
: 6, tokens
: true }).tokens
;
1361 const expected
= [false, false, false, false, false, false, false, false, true, false, false, false, false, false, false];
1363 describe("isOpeningBracketToken", () => {
1364 tokens
.forEach((token
, index
) => {
1365 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1366 assert
.strictEqual(astUtils
.isOpeningBracketToken(token
), expected
[index
]);
1371 describe("isNotOpeningBracketToken", () => {
1372 tokens
.forEach((token
, index
) => {
1373 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1374 assert
.strictEqual(astUtils
.isNotOpeningBracketToken(token
), !expected
[index
]);
1381 const code
= "if (obj && foo) { obj[foo](); }";
1382 const tokens
= espree
.parse(code
, { ecmaVersion
: 6, tokens
: true }).tokens
;
1383 const expected
= [false, true, false, false, false, false, false, false, false, false, false, true, false, false, false];
1385 describe("isOpeningParenToken", () => {
1386 tokens
.forEach((token
, index
) => {
1387 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1388 assert
.strictEqual(astUtils
.isOpeningParenToken(token
), expected
[index
]);
1393 describe("isNotOpeningParenToken", () => {
1394 tokens
.forEach((token
, index
) => {
1395 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1396 assert
.strictEqual(astUtils
.isNotOpeningParenToken(token
), !expected
[index
]);
1403 const code
= "if (obj && foo) { obj[foo](); }";
1404 const tokens
= espree
.parse(code
, { ecmaVersion
: 6, tokens
: true }).tokens
;
1405 const expected
= [false, false, false, false, false, false, false, false, false, false, false, false, false, true, false];
1407 describe("isSemicolonToken", () => {
1408 tokens
.forEach((token
, index
) => {
1409 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1410 assert
.strictEqual(astUtils
.isSemicolonToken(token
), expected
[index
]);
1415 describe("isNotSemicolonToken", () => {
1416 tokens
.forEach((token
, index
) => {
1417 it(`should return ${expected[index]} for '${token.value}'.`, () => {
1418 assert
.strictEqual(astUtils
.isNotSemicolonToken(token
), !expected
[index
]);
1424 describe("isNullLiteral", () => {
1425 const EXPECTED_RESULTS
= {
1434 Object
.keys(EXPECTED_RESULTS
).forEach(key
=> {
1435 it(`returns ${EXPECTED_RESULTS[key]} for ${key}`, () => {
1436 const ast
= espree
.parse(key
, { ecmaVersion
: 6 });
1438 assert
.strictEqual(astUtils
.isNullLiteral(ast
.body
[0].expression
), EXPECTED_RESULTS
[key
]);
1443 describe("createGlobalLinebreakMatcher", () => {
1444 it("returns a regular expression with the g flag", () => {
1445 assert
.instanceOf(astUtils
.createGlobalLinebreakMatcher(), RegExp
);
1446 assert(astUtils
.createGlobalLinebreakMatcher().toString().endsWith("/gu"));
1448 it("returns unique objects on each call", () => {
1449 const firstObject
= astUtils
.createGlobalLinebreakMatcher();
1450 const secondObject
= astUtils
.createGlobalLinebreakMatcher();
1452 assert
.notStrictEqual(firstObject
, secondObject
);
1454 describe("correctly matches linebreaks", () => {
1455 const LINE_COUNTS
= {
1461 "foo\r\u2028bar": 3,
1465 Object
.keys(LINE_COUNTS
).forEach(text
=> {
1467 assert
.strictEqual(text
.split(astUtils
.createGlobalLinebreakMatcher()).length
, LINE_COUNTS
[text
]);
1473 describe("canTokensBeAdjacent", () => {
1474 const CASES
= new Map([
1475 [["foo", "bar"], false],
1476 [[";foo", "bar"], false],
1477 [[";", "bar"], true],
1478 [[")", "bar"], true],
1479 [["foo0", "bar"], false],
1480 [["foo;", "bar"], true],
1481 [["foo", "0"], false],
1482 [["of", ".2"], true],
1483 [["2", ".2"], false],
1484 [["of", "'foo'"], true],
1485 [["foo", "`bar`"], true],
1486 [["`foo`", "in"], true],
1487 [["of", "0.2"], false],
1488 [["of", "0."], false],
1489 [[".2", "foo"], false],
1490 [["2.", "foo"], false],
1492 [["++", "-"], true],
1493 [["+", "--"], true],
1494 [["++", "--"], true],
1496 [["--", "+"], true],
1497 [["-", "++"], true],
1498 [["--", "++"], true],
1499 [["+", "+"], false],
1500 [["-", "-"], false],
1501 [["++", "+"], false],
1502 [["--", "-"], false],
1503 [["+", "++"], false],
1504 [["-", "--"], false],
1505 [["a/", "b"], true],
1506 [["a/", "+b"], true],
1507 [["a+", "/^regex$/"], true],
1508 [["a/", "/^regex$/"], false],
1509 [["a+", "/**/"], true],
1510 [["a+", "/**/b"], true],
1511 [["//", "a"], false],
1512 [["a/", "/**/b"], false],
1513 [["a+", "//"], true],
1514 [["a+", "//\nb"], true],
1515 [["a/", "//\nb"], false],
1516 [["/**/", "b"], true],
1517 [["a/**/", "b"], true],
1518 [["/**/a", "b"], false],
1519 [["a", "/**/b"], true],
1520 [["a", "b/**/"], false],
1521 [["a", "//\nb"], true],
1522 [["a", "b//"], false],
1523 [["#!/usr/bin/env node", "("], false],
1524 [["123invalidtoken", "("], false],
1525 [["(", "123invalidtoken"], false],
1526 [["(", "1n"], true],
1527 [["1n", "+"], true],
1528 [["1n", "in"], false],
1529 [["return", "#x"], true],
1530 [["yield", "#x"], true],
1531 [["get", "#x"], true]
1534 CASES
.forEach((expectedResult
, tokenStrings
) => {
1535 it(tokenStrings
.join(", "), () => {
1536 assert
.strictEqual(astUtils
.canTokensBeAdjacent(tokenStrings
[0], tokenStrings
[1]), expectedResult
);
1540 it("#!/usr/bin/env node, (", () => {
1542 astUtils
.canTokensBeAdjacent(
1543 { type
: "Shebang", value
: "#!/usr/bin/env node" },
1544 { type
: "Punctuator", value
: "(" }
1551 describe("equalTokens", () => {
1552 it("should return true if tokens are equal", () => {
1553 const code
= "a=0;a=0;";
1554 const ast
= espree
.parse(code
, ESPREE_CONFIG
);
1555 const sourceCode
= new SourceCode(code
, ast
);
1557 assert
.strictEqual(astUtils
.equalTokens(ast
.body
[0], ast
.body
[1], sourceCode
), true);
1560 it("should return false if tokens are not equal", () => {
1561 const code
= "a=0;a=1;";
1562 const ast
= espree
.parse(code
, ESPREE_CONFIG
);
1563 const sourceCode
= new SourceCode(code
, ast
);
1565 assert
.strictEqual(astUtils
.equalTokens(ast
.body
[0], ast
.body
[1], sourceCode
), false);
1569 describe("equalLiteralValue", () => {
1570 describe("should return true if two regex values are same, even if it's not supported natively.", () => {
1576 regex
: { pattern
: "(?:)", flags
: "u" }
1581 regex
: { pattern
: "(?:)", flags
: "u" }
1589 regex
: { pattern
: "(?:)", flags
: "u" }
1594 regex
: { pattern
: "(?:)", flags
: "u" }
1602 regex
: { pattern
: "(?:)", flags
: "u" }
1606 value
: /(?:)/, // eslint-disable-line require-unicode-regexp -- Checking non-Unicode regex
1607 regex
: { pattern
: "(?:)", flags
: "" }
1615 regex
: { pattern
: "(?:a)", flags
: "u" }
1620 regex
: { pattern
: "(?:b)", flags
: "u" }
1626 for (const { nodeA
, nodeB
, expected
} of patterns
) {
1627 it(`should return ${expected} if it compared ${util.format("%o", nodeA)} and ${util.format("%o", nodeB)}`, () => {
1628 assert
.strictEqual(astUtils
.equalLiteralValue(nodeA
, nodeB
), expected
);
1633 describe("should return true if two bigint values are same, even if it's not supported natively.", () => {
1689 for (const { nodeA
, nodeB
, expected
} of patterns
) {
1690 it(`should return ${expected} if it compared ${util.format("%o", nodeA)} and ${util.format("%o", nodeB)}`, () => {
1691 assert
.strictEqual(astUtils
.equalLiteralValue(nodeA
, nodeB
), expected
);
1697 describe("hasOctalOrNonOctalDecimalEscapeSequence", () => {
1699 /* eslint-disable quote-props -- Make consistent here for readability */
1700 const expectedResults
= {
1741 "foo\\\nbar\\2baz": true,
1743 "foo\\\nbar\\9baz": true,
1768 "foo\\\nbar": false,
1771 /* eslint-enable quote-props -- Make consistent here for readability */
1773 Object
.keys(expectedResults
).forEach(key
=> {
1774 it(`should return ${expectedResults[key]} for ${key}`, () => {
1775 const ast
= espree
.parse(`"${key}"`);
1777 assert
.strictEqual(astUtils
.hasOctalOrNonOctalDecimalEscapeSequence(ast
.body
[0].expression
.raw
), expectedResults
[key
]);
1782 describe("isLogicalAssignmentOperator", () => {
1783 const expectedResults
= {
1799 Object
.entries(expectedResults
).forEach(([key
, value
]) => {
1800 it(`should return ${value} for ${key}`, () => {
1801 assert
.strictEqual(astUtils
.isLogicalAssignmentOperator(key
), value
);