diff --git a/.eslintrc.js b/.eslintrc.js
index 4483568..5c970d2 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -12,7 +12,7 @@ module.exports = {
object: "context",
property: "getScope",
message:
- "If you are using it in a test case, use test/test-lib/get-scope.mjs instead. Other than that, the API should also be compatible with ESLint v9.",
+ "If you are using it in a test case, use test/test-lib/eslint-compat.mjs#getScope instead. Other than that, the API should also be compatible with ESLint v9.",
},
],
},
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3401dfe..aa3fd68 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -48,17 +48,33 @@ jobs:
matrix.os }})
strategy:
matrix:
- eslint: [8]
- node: [12.22.0, 12, 14.17.0, 14, 16, 18, 20, 22]
+ eslint: [9]
+ node: [18, 20, 22]
os: [ubuntu-latest]
include:
# On other platforms
- os: windows-latest
- eslint: 8
- node: 20
+ eslint: 9
+ node: 22
- os: macos-latest
- eslint: 8
- node: 20
+ eslint: 9
+ node: 22
+ # On old Node versions & ESLint v8
+ - eslint: 8
+ node: 12.22.0
+ os: ubuntu-latest
+ - eslint: 8
+ node: 12
+ os: ubuntu-latest
+ - eslint: 8
+ node: 14.17.0
+ os: ubuntu-latest
+ - eslint: 8
+ node: 14
+ os: ubuntu-latest
+ - eslint: 8
+ node: 16
+ os: ubuntu-latest
# On old ESLint versions
- eslint: 7
node: 20
diff --git a/test/find-variable.mjs b/test/find-variable.mjs
index 6b6e71c..6b0ec35 100644
--- a/test/find-variable.mjs
+++ b/test/find-variable.mjs
@@ -1,24 +1,33 @@
import assert from "assert"
-import eslint from "eslint"
import { findVariable } from "../src/index.mjs"
-import { getScope } from "./test-lib/get-scope.mjs"
+import { getScope, newCompatLinter } from "./test-lib/eslint-compat.mjs"
describe("The 'findVariable' function", () => {
function getVariable(code, selector, withString = null) {
- const linter = new eslint.Linter()
+ const linter = newCompatLinter()
let variable = null
- linter.defineRule("test", (context) => ({
- [selector](node) {
- variable = findVariable(
- getScope(context, node),
- withString || node,
- )
- },
- }))
linter.verify(code, {
- parserOptions: { ecmaVersion: 2020 },
- rules: { test: "error" },
+ languageOptions: { ecmaVersion: 2020 },
+ rules: { "test/test": "error" },
+ plugins: {
+ test: {
+ rules: {
+ test: {
+ create(context) {
+ return {
+ [selector](node) {
+ variable = findVariable(
+ getScope(context, node),
+ withString || node,
+ )
+ },
+ }
+ },
+ },
+ },
+ },
+ },
})
return variable
diff --git a/test/get-function-head-location.mjs b/test/get-function-head-location.mjs
index ace1724..5d73b00 100644
--- a/test/get-function-head-location.mjs
+++ b/test/get-function-head-location.mjs
@@ -2,6 +2,7 @@ import assert from "assert"
import eslint from "eslint"
import semver from "semver"
import { getFunctionHeadLocation } from "../src/index.mjs"
+import { newCompatLinter } from "./test-lib/eslint-compat.mjs"
describe("The 'getFunctionHeadLocation' function", () => {
const expectedResults = {
@@ -103,26 +104,37 @@ describe("The 'getFunctionHeadLocation' function", () => {
it(`should return "${JSON.stringify(
expectedLoc,
)}" for "${key}".`, () => {
- const linter = new eslint.Linter()
+ const linter = newCompatLinter()
let actualLoc = null
- linter.defineRule("test", (context) => ({
- ":function"(node) {
- actualLoc = getFunctionHeadLocation(
- node,
- context.getSourceCode(),
- )
- },
- }))
const messages = linter.verify(
key,
{
- rules: { test: "error" },
- parserOptions: {
+ rules: { "test/test": "error" },
+ languageOptions: {
ecmaVersion: semver.gte(eslint.Linter.version, "8.0.0")
? 2022
: 2020,
},
+ plugins: {
+ test: {
+ rules: {
+ test: {
+ create(context) {
+ return {
+ ":function"(node) {
+ actualLoc =
+ getFunctionHeadLocation(
+ node,
+ context.getSourceCode(),
+ )
+ },
+ }
+ },
+ },
+ },
+ },
+ },
},
"test.js",
true,
diff --git a/test/get-function-name-with-kind.mjs b/test/get-function-name-with-kind.mjs
index b29b6f4..5d1a36c 100644
--- a/test/get-function-name-with-kind.mjs
+++ b/test/get-function-name-with-kind.mjs
@@ -2,6 +2,7 @@ import assert from "assert"
import eslint from "eslint"
import semver from "semver"
import { getFunctionNameWithKind } from "../src/index.mjs"
+import { newCompatLinter } from "./test-lib/eslint-compat.mjs"
describe("The 'getFunctionNameWithKind' function", () => {
const expectedResults = {
@@ -133,22 +134,33 @@ describe("The 'getFunctionNameWithKind' function", () => {
const expectedResult2 = expectedResults[key]
it(`should return "${expectedResult1}" for "${key}".`, () => {
- const linter = new eslint.Linter()
+ const linter = newCompatLinter()
let actualResult = null
- linter.defineRule("test", () => ({
- ":function"(node) {
- actualResult = getFunctionNameWithKind(node)
- },
- }))
const messages = linter.verify(key, {
- rules: { test: "error" },
- parserOptions: {
+ rules: { "test/test": "error" },
+ languageOptions: {
ecmaVersion: semver.gte(eslint.Linter.version, "8.0.0")
? 2022
: 2020,
sourceType: "module",
},
+ plugins: {
+ test: {
+ rules: {
+ test: {
+ create(_context) {
+ return {
+ ":function"(node) {
+ actualResult =
+ getFunctionNameWithKind(node)
+ },
+ }
+ },
+ },
+ },
+ },
+ },
})
assert.strictEqual(
@@ -160,25 +172,36 @@ describe("The 'getFunctionNameWithKind' function", () => {
})
it(`should return "${expectedResult2}" for "${key}" if sourceCode is present.`, () => {
- const linter = new eslint.Linter()
+ const linter = newCompatLinter()
let actualResult = null
- linter.defineRule("test", (context) => ({
- ":function"(node) {
- actualResult = getFunctionNameWithKind(
- node,
- context.getSourceCode(),
- )
- },
- }))
const messages = linter.verify(key, {
- rules: { test: "error" },
- parserOptions: {
+ rules: { "test/test": "error" },
+ languageOptions: {
ecmaVersion: semver.gte(eslint.Linter.version, "8.0.0")
? 2022
: 2020,
sourceType: "module",
},
+ plugins: {
+ test: {
+ rules: {
+ test: {
+ create(context) {
+ return {
+ ":function"(node) {
+ actualResult =
+ getFunctionNameWithKind(
+ node,
+ context.getSourceCode(),
+ )
+ },
+ }
+ },
+ },
+ },
+ },
+ },
})
assert.strictEqual(
diff --git a/test/get-innermost-scope.mjs b/test/get-innermost-scope.mjs
index 4370327..e951060 100644
--- a/test/get-innermost-scope.mjs
+++ b/test/get-innermost-scope.mjs
@@ -1,75 +1,96 @@
import assert from "assert"
-import eslint from "eslint"
import { getInnermostScope } from "../src/index.mjs"
-import { getScope } from "./test-lib/get-scope.mjs"
+import { getScope, newCompatLinter } from "./test-lib/eslint-compat.mjs"
describe("The 'getInnermostScope' function", () => {
let i = 0
- for (const { code, parserOptions, selectNode, selectScope } of [
+ for (const { code, languageOptions, selectNode, selectScope } of [
{
code: "let a = 0",
- parserOptions: {},
+ languageOptions: {},
selectNode: (node) => node,
selectScope: (scope) => scope,
},
{
code: "let a = 0",
- parserOptions: { ecmaFeatures: { globalReturn: true } },
+ languageOptions: {
+ parserOptions: { ecmaFeatures: { globalReturn: true } },
+ },
selectNode: (node) => node,
selectScope: (scope) => scope.childScopes[0],
},
{
code: "let a = 0",
- parserOptions: { sourceType: "module" },
+ languageOptions: { sourceType: "module" },
selectNode: (node) => node,
selectScope: (scope) => scope.childScopes[0],
},
{
code: "a; { b; { c; } d; } e;",
- parserOptions: {},
+ languageOptions: {},
selectNode: (node) => node.body[0],
selectScope: (scope) => scope,
},
{
code: "a; { b; { c; } d; } e;",
- parserOptions: {},
+ languageOptions: {},
selectNode: (node) => node.body[2],
selectScope: (scope) => scope,
},
{
code: "a; { b; { c; } d; } e;",
- parserOptions: {},
+ languageOptions: {},
selectNode: (node) => node.body[1].body[0],
selectScope: (scope) => scope.childScopes[0],
},
{
code: "a; { b; { c; } d; } e;",
- parserOptions: {},
+ languageOptions: {},
selectNode: (node) => node.body[1].body[2],
selectScope: (scope) => scope.childScopes[0],
},
{
code: "a; { b; { c; } d; } e;",
- parserOptions: {},
+ languageOptions: {},
selectNode: (node) => node.body[1].body[1].body[0],
selectScope: (scope) => scope.childScopes[0].childScopes[0],
},
]) {
it(`should return the innermost scope (${++i})`, () => {
- const linter = new eslint.Linter()
+ const linter = newCompatLinter()
let actualScope = null
let expectedScope = null
- linter.defineRule("test", (context) => ({
- Program(node) {
- const scope = getScope(context, node)
- actualScope = getInnermostScope(scope, selectNode(node))
- expectedScope = selectScope(scope)
- },
- }))
linter.verify(code, {
- parserOptions: { ecmaVersion: 2020, ...parserOptions },
- rules: { test: "error" },
+ languageOptions: {
+ ecmaVersion: 2020,
+ sourceType: "script",
+ ...languageOptions,
+ },
+ rules: { "test/test": "error" },
+ plugins: {
+ test: {
+ rules: {
+ test: {
+ create(context) {
+ return {
+ Program(node) {
+ const scope = getScope(
+ context,
+ node,
+ )
+ actualScope = getInnermostScope(
+ scope,
+ selectNode(node),
+ )
+ expectedScope = selectScope(scope)
+ },
+ }
+ },
+ },
+ },
+ },
+ },
})
assert.notStrictEqual(expectedScope, null)
diff --git a/test/get-property-name.mjs b/test/get-property-name.mjs
index 4ced068..8afa8bb 100644
--- a/test/get-property-name.mjs
+++ b/test/get-property-name.mjs
@@ -2,6 +2,7 @@ import assert from "assert"
import eslint from "eslint"
import semver from "semver"
import { getPropertyName } from "../src/index.mjs"
+import { newCompatLinter } from "./test-lib/eslint-compat.mjs"
describe("The 'getPropertyName' function", () => {
for (const { code, expected } of [
@@ -56,23 +57,33 @@ describe("The 'getPropertyName' function", () => {
: []),
]) {
it(`should return ${JSON.stringify(expected)} from ${code}`, () => {
- const linter = new eslint.Linter()
+ const linter = newCompatLinter()
let actual = null
- linter.defineRule("test", () => ({
- "Property,PropertyDefinition,MethodDefinition,MemberExpression"(
- node,
- ) {
- actual = getPropertyName(node)
- },
- }))
const messages = linter.verify(code, {
- parserOptions: {
+ languageOptions: {
ecmaVersion: semver.gte(eslint.Linter.version, "8.0.0")
? 2022
: 2020,
},
- rules: { test: "error" },
+ rules: { "test/test": "error" },
+ plugins: {
+ test: {
+ rules: {
+ test: {
+ create(_context) {
+ return {
+ "Property,PropertyDefinition,MethodDefinition,MemberExpression"(
+ node,
+ ) {
+ actual = getPropertyName(node)
+ },
+ }
+ },
+ },
+ },
+ },
+ },
})
assert.strictEqual(
messages.length,
diff --git a/test/get-static-value.mjs b/test/get-static-value.mjs
index 9ca05c6..7424be7 100644
--- a/test/get-static-value.mjs
+++ b/test/get-static-value.mjs
@@ -2,7 +2,7 @@ import assert from "assert"
import eslint from "eslint"
import semver from "semver"
import { getStaticValue } from "../src/index.mjs"
-import { getScope } from "./test-lib/get-scope.mjs"
+import { getScope, newCompatLinter } from "./test-lib/eslint-compat.mjs"
describe("The 'getStaticValue' function", () => {
for (const { code, expected, noScope = false } of [
@@ -399,25 +399,36 @@ const aMap = Object.freeze({
: []),
]) {
it(`should return ${JSON.stringify(expected)} from ${code}`, () => {
- const linter = new eslint.Linter()
+ const linter = newCompatLinter()
let actual = null
- linter.defineRule("test", (context) => ({
- ExpressionStatement(node) {
- actual = getStaticValue(
- node,
- noScope ? null : getScope(context, node),
- )
- },
- }))
const messages = linter.verify(code, {
- env: { es6: true },
- parserOptions: {
+ languageOptions: {
ecmaVersion: semver.gte(eslint.Linter.version, "8.0.0")
? 2022
: 2020,
},
- rules: { test: "error" },
+ rules: { "test/test": "error" },
+ plugins: {
+ test: {
+ rules: {
+ test: {
+ create(context) {
+ return {
+ ExpressionStatement(node) {
+ actual = getStaticValue(
+ node,
+ noScope
+ ? null
+ : getScope(context, node),
+ )
+ },
+ }
+ },
+ },
+ },
+ },
+ },
})
assert.strictEqual(
diff --git a/test/get-string-if-constant.mjs b/test/get-string-if-constant.mjs
index 5d8cba0..c87baf1 100644
--- a/test/get-string-if-constant.mjs
+++ b/test/get-string-if-constant.mjs
@@ -1,7 +1,6 @@
import assert from "assert"
-import eslint from "eslint"
import { getStringIfConstant } from "../src/index.mjs"
-import { getScope } from "./test-lib/get-scope.mjs"
+import { getScope, newCompatLinter } from "./test-lib/eslint-compat.mjs"
describe("The 'getStringIfConstant' function", () => {
for (const { code, expected } of [
@@ -23,17 +22,29 @@ describe("The 'getStringIfConstant' function", () => {
{ code: "/(?\\w+)\\k/gu", expected: "/(?\\w+)\\k/gu" },
]) {
it(`should return ${JSON.stringify(expected)} from ${code}`, () => {
- const linter = new eslint.Linter()
+ const linter = newCompatLinter()
let actual = null
- linter.defineRule("test", () => ({
- "Program > ExpressionStatement > *"(node) {
- actual = getStringIfConstant(node)
- },
- }))
linter.verify(code, {
- parserOptions: { ecmaVersion: 2020 },
- rules: { test: "error" },
+ languageOptions: { ecmaVersion: 2020 },
+ rules: { "test/test": "error" },
+ plugins: {
+ test: {
+ rules: {
+ test: {
+ create(_context) {
+ return {
+ "Program > ExpressionStatement > *"(
+ node,
+ ) {
+ actual = getStringIfConstant(node)
+ },
+ }
+ },
+ },
+ },
+ },
+ },
})
assert.strictEqual(actual, expected)
@@ -51,20 +62,32 @@ describe("The 'getStringIfConstant' function", () => {
{ code: "const id = otherId; id", expected: null },
]) {
it(`should return ${JSON.stringify(expected)} from ${code}`, () => {
- const linter = new eslint.Linter()
+ const linter = newCompatLinter()
let actual = null
- linter.defineRule("test", (context) => ({
- "Program > ExpressionStatement > *"(node) {
- actual = getStringIfConstant(
- node,
- getScope(context, node),
- )
- },
- }))
linter.verify(code, {
- parserOptions: { ecmaVersion: 2020 },
- rules: { test: "error" },
+ languageOptions: { ecmaVersion: 2020 },
+ rules: { "test/test": "error" },
+ plugins: {
+ test: {
+ rules: {
+ test: {
+ create(context) {
+ return {
+ "Program > ExpressionStatement > *"(
+ node,
+ ) {
+ actual = getStringIfConstant(
+ node,
+ getScope(context, node),
+ )
+ },
+ }
+ },
+ },
+ },
+ },
+ },
})
assert.strictEqual(actual, expected)
diff --git a/test/has-side-effect.mjs b/test/has-side-effect.mjs
index c9f190f..80f5dba 100644
--- a/test/has-side-effect.mjs
+++ b/test/has-side-effect.mjs
@@ -3,6 +3,7 @@ import { getProperty } from "dot-prop"
import eslint from "eslint"
import semver from "semver"
import { hasSideEffect } from "../src/index.mjs"
+import { newCompatLinter } from "./test-lib/eslint-compat.mjs"
describe("The 'hasSideEffect' function", () => {
for (const { code, key = "body[0].expression", options, expected } of [
@@ -303,26 +304,35 @@ describe("The 'hasSideEffect' function", () => {
it(`should return ${expected} on the code \`${code}\` and the options \`${JSON.stringify(
options,
)}\``, () => {
- const linter = new eslint.Linter()
+ const linter = newCompatLinter()
let actual = null
- linter.defineRule("test", (context) => ({
- Program(node) {
- actual = hasSideEffect(
- getProperty(node, key),
- context.getSourceCode(),
- options,
- )
- },
- }))
const messages = linter.verify(code, {
- env: { es6: true },
- parserOptions: {
+ languageOptions: {
ecmaVersion: semver.gte(eslint.Linter.version, "8.0.0")
? 2022
: 2020,
},
- rules: { test: "error" },
+ rules: { "test/test": "error" },
+ plugins: {
+ test: {
+ rules: {
+ test: {
+ create(context) {
+ return {
+ Program(node) {
+ actual = hasSideEffect(
+ getProperty(node, key),
+ context.getSourceCode(),
+ options,
+ )
+ },
+ }
+ },
+ },
+ },
+ },
+ },
})
assert.strictEqual(
diff --git a/test/is-parenthesized.mjs b/test/is-parenthesized.mjs
index 3bcb1e6..832251d 100644
--- a/test/is-parenthesized.mjs
+++ b/test/is-parenthesized.mjs
@@ -1,7 +1,7 @@
import assert from "assert"
import { getProperty } from "dot-prop"
-import eslint from "eslint"
import { isParenthesized } from "../src/index.mjs"
+import { newCompatLinter } from "./test-lib/eslint-compat.mjs"
describe("The 'isParenthesized' function", () => {
for (const { code, expected } of [
@@ -219,21 +219,33 @@ describe("The 'isParenthesized' function", () => {
describe(`on the code \`${code}\``, () => {
for (const key of Object.keys(expected)) {
it(`should return ${expected[key]} at "${key}"`, () => {
- const linter = new eslint.Linter()
+ const linter = newCompatLinter()
let actual = null
- linter.defineRule("test", (context) => ({
- Program(node) {
- actual = isParenthesized(
- getProperty(node, key),
- context.getSourceCode(),
- )
- },
- }))
const messages = linter.verify(code, {
- env: { es6: true },
- parserOptions: { ecmaVersion: 2020 },
- rules: { test: "error" },
+ languageOptions: {
+ ecmaVersion: 2020,
+ sourceType: "script",
+ },
+ rules: { "test/test": "error" },
+ plugins: {
+ test: {
+ rules: {
+ test: {
+ create(context) {
+ return {
+ Program(node) {
+ actual = isParenthesized(
+ getProperty(node, key),
+ context.getSourceCode(),
+ )
+ },
+ }
+ },
+ },
+ },
+ },
+ },
})
assert.strictEqual(
@@ -294,22 +306,31 @@ describe("The 'isParenthesized' function", () => {
describe(`on the code \`${code}\` and 2 times`, () => {
for (const key of Object.keys(expected)) {
it(`should return ${expected[key]} at "${key}"`, () => {
- const linter = new eslint.Linter()
+ const linter = newCompatLinter()
let actual = null
- linter.defineRule("test", (context) => ({
- Program(node) {
- actual = isParenthesized(
- 2,
- getProperty(node, key),
- context.getSourceCode(),
- )
- },
- }))
const messages = linter.verify(code, {
- env: { es6: true },
- parserOptions: { ecmaVersion: 2020 },
- rules: { test: "error" },
+ languageOptions: { ecmaVersion: 2020 },
+ rules: { "test/test": "error" },
+ plugins: {
+ test: {
+ rules: {
+ test: {
+ create(context) {
+ return {
+ Program(node) {
+ actual = isParenthesized(
+ 2,
+ getProperty(node, key),
+ context.getSourceCode(),
+ )
+ },
+ }
+ },
+ },
+ },
+ },
+ },
})
assert.strictEqual(
diff --git a/test/reference-tracker.mjs b/test/reference-tracker.mjs
index 6e9f14a..b36ce42 100644
--- a/test/reference-tracker.mjs
+++ b/test/reference-tracker.mjs
@@ -2,15 +2,15 @@ import assert from "assert"
import eslint from "eslint"
import semver from "semver"
import { CALL, CONSTRUCT, ESM, READ, ReferenceTracker } from "../src/index.mjs"
-import { getScope } from "./test-lib/get-scope.mjs"
+import { getScope, newCompatLinter } from "./test-lib/eslint-compat.mjs"
const config = {
- parserOptions: {
+ languageOptions: {
ecmaVersion: semver.gte(eslint.Linter.version, "8.0.0") ? 2022 : 2020,
sourceType: "module",
+ globals: { Reflect: false },
},
- globals: { Reflect: false },
- rules: { test: "error" },
+ rules: { "test/test": "error" },
}
describe("The 'ReferenceTracker' class:", () => {
@@ -517,29 +517,48 @@ describe("The 'ReferenceTracker' class:", () => {
: []),
]) {
it(description, () => {
- const linter = new eslint.Linter()
+ const linter = newCompatLinter()
let actual = null
- linter.defineRule("test", (context) => ({
- "Program:exit"(node) {
- const tracker = new ReferenceTracker(
- getScope(context, node),
- )
- actual = Array.from(
- tracker.iterateGlobalReferences(traceMap),
- ).map((x) =>
- Object.assign(x, {
- node: {
- type: x.node.type,
- ...(x.node.optional
- ? { optional: x.node.optional }
- : {}),
+ linter.verify(code, {
+ ...config,
+ plugins: {
+ test: {
+ rules: {
+ test: {
+ create(context) {
+ return {
+ "Program:exit"(node) {
+ const tracker =
+ new ReferenceTracker(
+ getScope(context, node),
+ )
+ actual = Array.from(
+ tracker.iterateGlobalReferences(
+ traceMap,
+ ),
+ ).map((x) =>
+ Object.assign(x, {
+ node: {
+ type: x.node.type,
+ ...(x.node.optional
+ ? {
+ optional:
+ x.node
+ .optional,
+ }
+ : {}),
+ },
+ }),
+ )
+ },
+ }
+ },
},
- }),
- )
+ },
+ },
},
- }))
- linter.verify(code, config)
+ })
assert.deepStrictEqual(actual, expected)
})
@@ -683,29 +702,48 @@ describe("The 'ReferenceTracker' class:", () => {
},
]) {
it(description, () => {
- const linter = new eslint.Linter()
+ const linter = newCompatLinter()
let actual = null
- linter.defineRule("test", (context) => ({
- "Program:exit"(node) {
- const tracker = new ReferenceTracker(
- getScope(context, node),
- )
- actual = Array.from(
- tracker.iterateCjsReferences(traceMap),
- ).map((x) =>
- Object.assign(x, {
- node: {
- type: x.node.type,
- ...(x.node.optional
- ? { optional: x.node.optional }
- : {}),
+ linter.verify(code, {
+ ...config,
+ plugins: {
+ test: {
+ rules: {
+ test: {
+ create(context) {
+ return {
+ "Program:exit"(node) {
+ const tracker =
+ new ReferenceTracker(
+ getScope(context, node),
+ )
+ actual = Array.from(
+ tracker.iterateCjsReferences(
+ traceMap,
+ ),
+ ).map((x) =>
+ Object.assign(x, {
+ node: {
+ type: x.node.type,
+ ...(x.node.optional
+ ? {
+ optional:
+ x.node
+ .optional,
+ }
+ : {}),
+ },
+ }),
+ )
+ },
+ }
+ },
},
- }),
- )
+ },
+ },
},
- }))
- linter.verify(code, config)
+ })
assert.deepStrictEqual(actual, expected)
})
@@ -967,29 +1005,48 @@ describe("The 'ReferenceTracker' class:", () => {
},
]) {
it(description, () => {
- const linter = new eslint.Linter()
+ const linter = newCompatLinter()
let actual = null
- linter.defineRule("test", (context) => ({
- "Program:exit"(node) {
- const tracker = new ReferenceTracker(
- getScope(context, node),
- )
- actual = Array.from(
- tracker.iterateEsmReferences(traceMap),
- ).map((x) =>
- Object.assign(x, {
- node: {
- type: x.node.type,
- ...(x.node.optional
- ? { optional: x.node.optional }
- : {}),
+ linter.verify(code, {
+ ...config,
+ plugins: {
+ test: {
+ rules: {
+ test: {
+ create(context) {
+ return {
+ "Program:exit"(node) {
+ const tracker =
+ new ReferenceTracker(
+ getScope(context, node),
+ )
+ actual = Array.from(
+ tracker.iterateEsmReferences(
+ traceMap,
+ ),
+ ).map((x) =>
+ Object.assign(x, {
+ node: {
+ type: x.node.type,
+ ...(x.node.optional
+ ? {
+ optional:
+ x.node
+ .optional,
+ }
+ : {}),
+ },
+ }),
+ )
+ },
+ }
+ },
},
- }),
- )
+ },
+ },
},
- }))
- linter.verify(code, config)
+ })
assert.deepStrictEqual(actual, expected)
})
diff --git a/test/test-lib/eslint-compat.mjs b/test/test-lib/eslint-compat.mjs
new file mode 100644
index 0000000..55d98e8
--- /dev/null
+++ b/test/test-lib/eslint-compat.mjs
@@ -0,0 +1,62 @@
+import eslint from "eslint"
+import semver from "semver"
+
+export function getScope(context, node) {
+ const sourceCode = context.sourceCode || context.getSourceCode()
+ if (sourceCode.getScope) {
+ return sourceCode.getScope(node)
+ }
+ const scopeManager = sourceCode.scopeManager
+ const inner = node.type !== "Program"
+ for (let n = node; n; n = n.parent) {
+ const scope = scopeManager.acquire(n, inner)
+ if (scope) {
+ if (scope.type === "function-expression-name") {
+ return scope.childScopes[0]
+ }
+ return scope
+ }
+ }
+ return scopeManager.scopes[0]
+}
+
+export function newCompatLinter() {
+ if (semver.gte(eslint.Linter.version, "9.0.0-0")) {
+ return new eslint.Linter()
+ }
+
+ const linter = new eslint.Linter()
+ return {
+ verify(code, config) {
+ const newConfig = { ...config }
+ if (newConfig.languageOptions) {
+ const languageOptions = newConfig.languageOptions
+ delete newConfig.languageOptions
+ newConfig.parserOptions = {
+ ...newConfig.parserOptions,
+ ...languageOptions.parserOptions,
+ ...languageOptions,
+ }
+ if (languageOptions.globals) {
+ newConfig.globals = {
+ ...newConfig.globals,
+ ...languageOptions.globals,
+ }
+ }
+ }
+ if (newConfig.plugins) {
+ const plugins = newConfig.plugins
+ delete newConfig.plugins
+ for (const [pluginName, plugin] of Object.entries(plugins)) {
+ for (const [ruleName, rule] of Object.entries(
+ plugin.rules || {},
+ )) {
+ linter.defineRule(`${pluginName}/${ruleName}`, rule)
+ }
+ }
+ }
+ newConfig.env = { ...newConfig.env, es6: true }
+ return linter.verify(code, newConfig)
+ },
+ }
+}
diff --git a/test/test-lib/get-scope.mjs b/test/test-lib/get-scope.mjs
deleted file mode 100644
index 765b6c8..0000000
--- a/test/test-lib/get-scope.mjs
+++ /dev/null
@@ -1,18 +0,0 @@
-export function getScope(context, node) {
- const sourceCode = context.sourceCode || context.getSourceCode()
- if (sourceCode.getScope) {
- return sourceCode.getScope(node)
- }
- const scopeManager = sourceCode.scopeManager
- const inner = node.type !== "Program"
- for (let n = node; n; n = n.parent) {
- const scope = scopeManager.acquire(n, inner)
- if (scope) {
- if (scope.type === "function-expression-name") {
- return scope.childScopes[0]
- }
- return scope
- }
- }
- return scopeManager.scopes[0]
-}