From 229f26f62f06588c07e949ffe2fbe99678b3194f Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Wed, 10 Jan 2024 17:45:49 +0900 Subject: [PATCH 1/3] test: add test for eslint v9 --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d745794..f8dca5b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,6 +53,10 @@ jobs: - os: macos-latest eslint: 8 node: 18 + # On next ESLint version + - eslint: ^9.0.0-0 + node: 20 + os: ubuntu-latest # On old ESLint versions - eslint: 7 node: 18 From 9c69f8bea4da5e136a4a123127dcf43fbe24dd15 Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Wed, 10 Jan 2024 18:40:49 +0900 Subject: [PATCH 2/3] fix --- .eslintrc.js | 2 +- test/find-variable.mjs | 35 ++++-- test/get-function-head-location.mjs | 34 +++-- test/get-function-name-with-kind.mjs | 61 ++++++--- test/get-innermost-scope.mjs | 63 ++++++---- test/get-property-name.mjs | 31 +++-- test/get-static-value.mjs | 37 ++++-- test/get-string-if-constant.mjs | 65 ++++++---- test/has-side-effect.mjs | 36 ++++-- test/is-parenthesized.mjs | 73 +++++++---- test/reference-tracker.mjs | 179 ++++++++++++++++++--------- test/test-lib/eslint-compat.mjs | 62 ++++++++++ test/test-lib/get-scope.mjs | 18 --- 13 files changed, 469 insertions(+), 227 deletions(-) create mode 100644 test/test-lib/eslint-compat.mjs delete mode 100644 test/test-lib/get-scope.mjs 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/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] -} From a1fd76d1ac69a3a91cc4db91cf863e9225e8bbc2 Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Sat, 6 Apr 2024 10:53:03 +0900 Subject: [PATCH 3/3] test: update workflow --- .github/workflows/ci.yml | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f8dca5b..f079d34 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,20 +42,29 @@ jobs: matrix.os }}) strategy: matrix: - eslint: [8] - node: [12.22.0, 12, 14.17.0, 14, 16, 18, 20] + eslint: [9] + node: [18, 20] os: [ubuntu-latest] include: # On other platforms - os: windows-latest - eslint: 8 + eslint: 9 node: 18 - os: macos-latest - eslint: 8 + eslint: 9 node: 18 - # On next ESLint version - - eslint: ^9.0.0-0 - node: 20 + # 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: 16 os: ubuntu-latest # On old ESLint versions - eslint: 7