From 4d1723332eb337b972bf2b61eff22bdea5bf1c68 Mon Sep 17 00:00:00 2001 From: JounQin Date: Sun, 24 Mar 2024 20:21:40 +0800 Subject: [PATCH] feat: use eslint-compat-utils to support eslint v9 fix #60 close #61 --- package.json | 1 + patches/eslint-compat-utils+0.5.0.patch | 40 ++++++++++++++++++++ src/rules/consistent-type-specifier-style.ts | 3 +- src/rules/dynamic-import-chunkname.ts | 3 +- src/rules/first.ts | 11 +++++- src/rules/named.ts | 9 ++--- src/rules/namespace.ts | 13 +++++-- src/rules/newline-after-import.ts | 14 +++---- src/rules/no-absolute-path.ts | 6 +-- src/rules/no-amd.ts | 4 +- src/rules/no-commonjs.ts | 10 ++--- src/rules/no-cycle.ts | 6 +-- src/rules/no-default-export.ts | 6 ++- src/rules/no-deprecated.ts | 7 +++- src/rules/no-duplicates.ts | 3 +- src/rules/no-empty-named-blocks.ts | 3 +- src/rules/no-extraneous-dependencies.ts | 9 ++--- src/rules/no-import-module-exports.ts | 11 ++---- src/rules/no-mutable-exports.ts | 6 +-- src/rules/no-named-as-default-member.ts | 2 +- src/rules/no-named-as-default.ts | 2 +- src/rules/no-namespace.ts | 7 ++-- src/rules/no-relative-packages.ts | 5 +-- src/rules/no-relative-parent-imports.ts | 6 +-- src/rules/no-restricted-paths.ts | 5 +-- src/rules/no-self-import.ts | 5 +-- src/rules/no-unassigned-import.ts | 5 +-- src/rules/no-unused-modules.ts | 5 +-- src/rules/no-useless-path-segments.ts | 8 ++-- src/rules/order.ts | 9 +++-- src/utils/declared-scope.ts | 12 +++++- src/utils/get-ancestors.ts | 13 +++++++ src/utils/get-scope.ts | 13 +++++++ src/utils/import-declaration.ts | 9 ++++- src/utils/index.ts | 2 + src/utils/package-path.ts | 8 ++-- src/utils/resolve.ts | 10 ++--- yarn.lock | 7 ++++ 38 files changed, 192 insertions(+), 106 deletions(-) create mode 100644 patches/eslint-compat-utils+0.5.0.patch create mode 100644 src/utils/get-ancestors.ts create mode 100644 src/utils/get-scope.ts diff --git a/package.json b/package.json index 4b37796c4..7a7700014 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "@typescript-eslint/utils": "^5.62.0", "debug": "^4.3.4", "doctrine": "^3.0.0", + "eslint-compat-utils": "^0.5.0", "eslint-import-resolver-node": "^0.3.9", "get-tsconfig": "^4.7.3", "is-glob": "^4.0.3", diff --git a/patches/eslint-compat-utils+0.5.0.patch b/patches/eslint-compat-utils+0.5.0.patch new file mode 100644 index 000000000..40abe5f67 --- /dev/null +++ b/patches/eslint-compat-utils+0.5.0.patch @@ -0,0 +1,40 @@ +diff --git a/node_modules/eslint-compat-utils/dist/index.d.ts b/node_modules/eslint-compat-utils/dist/index.d.ts +index 993098a..ccb61ad 100644 +--- a/node_modules/eslint-compat-utils/dist/index.d.ts ++++ b/node_modules/eslint-compat-utils/dist/index.d.ts +@@ -1,21 +1,23 @@ +-import { Rule, SourceCode } from 'eslint'; ++import { TSESLint } from '@typescript-eslint/utils' ++ ++type RuleContext = TSESLint.RuleContext + + /** + * Returns an extended instance of `context.sourceCode` or the result of `context.getSourceCode()`. + * Extended instances can use new APIs such as `getScope(node)` even with old ESLint. + */ +-declare function getSourceCode(context: Rule.RuleContext): SourceCode; ++declare function getSourceCode(context: RuleContext): TSESLint.SourceCode; + + /** + * Gets the value of `context.cwd`, but for older ESLint it returns the result of `context.getCwd()`. + * Versions older than v6.6.0 return a value from the result of `process.cwd()`. + */ +-declare function getCwd(context: Rule.RuleContext): string; ++declare function getCwd(context: RuleContext): string; + + /** + * Gets the value of `context.filename`, but for older ESLint it returns the result of `context.getFilename()`. + */ +-declare function getFilename(context: Rule.RuleContext): string; ++declare function getFilename(context: RuleContext): string; + + /** + * Gets the value of `context.physicalFilename`, +@@ -23,6 +25,6 @@ declare function getFilename(context: Rule.RuleContext): string; + * Versions older than v7.28.0 return a value guessed from the result of `context.getFilename()`, + * but it may be incorrect. + */ +-declare function getPhysicalFilename(context: Rule.RuleContext): string; ++declare function getPhysicalFilename(context: RuleContext): string; + + export { getCwd, getFilename, getPhysicalFilename, getSourceCode }; diff --git a/src/rules/consistent-type-specifier-style.ts b/src/rules/consistent-type-specifier-style.ts index fb19e7787..3efc04728 100644 --- a/src/rules/consistent-type-specifier-style.ts +++ b/src/rules/consistent-type-specifier-style.ts @@ -1,4 +1,5 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils' +import { getSourceCode } from 'eslint-compat-utils' import { createRule } from '../utils' @@ -73,7 +74,7 @@ export = createRule<[Options?], MessageId>({ }, defaultOptions: [], create(context) { - const sourceCode = context.getSourceCode() + const sourceCode = getSourceCode(context) if (context.options[0] === 'prefer-inline') { return { diff --git a/src/rules/dynamic-import-chunkname.ts b/src/rules/dynamic-import-chunkname.ts index 51d54da19..415ce2d27 100644 --- a/src/rules/dynamic-import-chunkname.ts +++ b/src/rules/dynamic-import-chunkname.ts @@ -1,6 +1,7 @@ import vm from 'node:vm' import type { TSESTree } from '@typescript-eslint/utils' +import { getSourceCode } from 'eslint-compat-utils' import { createRule } from '../utils' @@ -74,7 +75,7 @@ export = createRule<[Options?], MessageId>({ const chunkSubstrRegex = new RegExp(chunkSubstrFormat) function run(node: TSESTree.Node, arg: TSESTree.Node) { - const sourceCode = context.getSourceCode() + const sourceCode = getSourceCode(context) const leadingComments = sourceCode.getCommentsBefore(arg) if ((!leadingComments || leadingComments.length === 0) && !allowEmpty) { diff --git a/src/rules/first.ts b/src/rules/first.ts index d39291f5a..37c36d03e 100644 --- a/src/rules/first.ts +++ b/src/rules/first.ts @@ -1,5 +1,7 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils' +import { getSourceCode } from 'eslint-compat-utils' +import type { RuleContext } from '../types' import { createRule } from '../utils' function getImportValue(node: TSESTree.ProgramStatement) { @@ -51,7 +53,7 @@ export = createRule<['absolute-first'?], MessageId>({ } const absoluteFirst = context.options[0] === 'absolute-first' - const sourceCode = context.getSourceCode() + const sourceCode = getSourceCode(context) const originSourceCode = sourceCode.getText() let nonImportCount = 0 @@ -95,7 +97,12 @@ export = createRule<['absolute-first'?], MessageId>({ } if (nonImportCount > 0) { - for (const variable of context.getDeclaredVariables(node)) { + /** + * @see https://eslint.org/docs/next/use/migrate-to-9.0.0#-removed-multiple-context-methods + */ + for (const variable of ( + sourceCode as unknown as RuleContext + ).getDeclaredVariables(node)) { if (!shouldSort) { break } diff --git a/src/rules/named.ts b/src/rules/named.ts index 3c30053f0..bddfa8437 100644 --- a/src/rules/named.ts +++ b/src/rules/named.ts @@ -1,6 +1,7 @@ import path from 'node:path' import type { TSESTree } from '@typescript-eslint/utils' +import { getFilename, getPhysicalFilename } from 'eslint-compat-utils' import { ExportMap, createRule } from '../utils' import type { ModuleOptions } from '../utils' @@ -97,11 +98,7 @@ export = createRule<[ModuleOptions?], MessageId>({ const deepPath = deepLookup.path .map(i => path.relative( - path.dirname( - context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename(), - ), + path.dirname(getPhysicalFilename(context)), i.path, ), ) @@ -200,7 +197,7 @@ export = createRule<[ModuleOptions?], MessageId>({ if (deepLookup.path.length > 1) { const deepPath = deepLookup.path .map(i => - path.relative(path.dirname(context.getFilename()), i.path), + path.relative(path.dirname(getFilename(context)), i.path), ) .join(' -> ') diff --git a/src/rules/namespace.ts b/src/rules/namespace.ts index fdbc6bbca..0444948e8 100644 --- a/src/rules/namespace.ts +++ b/src/rules/namespace.ts @@ -152,7 +152,7 @@ export = createRule<[Options], MessageId>({ // same as above, but does not add names to local map ExportNamespaceSpecifier(namespace) { - const declaration = importDeclaration(context) + const declaration = importDeclaration(context, namespace) const imports = ExportMap.get(declaration.source.value, context) if (imports == null) { @@ -186,7 +186,10 @@ export = createRule<[Options], MessageId>({ return } - if (declaredScope(context, dereference.object.name) !== 'module') { + if ( + declaredScope(context, dereference, dereference.object.name) !== + 'module' + ) { return } @@ -249,7 +252,9 @@ export = createRule<[Options], MessageId>({ } }, - VariableDeclarator({ id, init }) { + VariableDeclarator(node) { + const { id, init } = node + if (init == null) { return } @@ -261,7 +266,7 @@ export = createRule<[Options], MessageId>({ } // check for redefinition in intermediate scopes - if (declaredScope(context, init.name) !== 'module') { + if (declaredScope(context, node, init.name) !== 'module') { return } diff --git a/src/rules/newline-after-import.ts b/src/rules/newline-after-import.ts index 67b9dc864..47fb1ba32 100644 --- a/src/rules/newline-after-import.ts +++ b/src/rules/newline-after-import.ts @@ -4,8 +4,9 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils' import debug from 'debug' +import { getPhysicalFilename } from 'eslint-compat-utils' -import { isStaticRequire, createRule } from '../utils' +import { isStaticRequire, createRule, getScope } from '../utils' const log = debug('eslint-plugin-import-x:rules:newline-after-import') @@ -267,14 +268,9 @@ export = createRule<[Options?], MessageId>({ requireCalls.push(node) } }, - 'Program:exit'() { - log( - 'exit processing for', - context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename(), - ) - const scopeBody = getScopeBody(context.getScope()) + 'Program:exit'(node) { + log('exit processing for', getPhysicalFilename(context)) + const scopeBody = getScopeBody(getScope(context, node)) log('got scope:', scopeBody) diff --git a/src/rules/no-absolute-path.ts b/src/rules/no-absolute-path.ts index da723e84f..fbf2306f8 100644 --- a/src/rules/no-absolute-path.ts +++ b/src/rules/no-absolute-path.ts @@ -1,5 +1,7 @@ import path from 'node:path' +import { getPhysicalFilename } from 'eslint-compat-utils' + import { isAbsolute, createRule, @@ -35,9 +37,7 @@ export = createRule<[ModuleOptions?], MessageId>({ node: source, messageId: 'absolute', fix(fixer) { - const resolvedContext = context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename() + const resolvedContext = getPhysicalFilename(context) // node.js and web imports work with posix style paths ("/") let relativePath = path.posix.relative( path.dirname(resolvedContext), diff --git a/src/rules/no-amd.ts b/src/rules/no-amd.ts index fac2c7145..6d56f0a6e 100644 --- a/src/rules/no-amd.ts +++ b/src/rules/no-amd.ts @@ -2,7 +2,7 @@ * Rule to prefer imports to AMD */ -import { createRule } from '../utils' +import { createRule, getScope } from '../utils' type MessageId = 'amd' @@ -23,7 +23,7 @@ export = createRule<[], MessageId>({ create(context) { return { CallExpression(node) { - if (context.getScope().type !== 'module') { + if (getScope(context, node).type !== 'module') { return } diff --git a/src/rules/no-commonjs.ts b/src/rules/no-commonjs.ts index 7b5dfaad3..9e9edbd7d 100644 --- a/src/rules/no-commonjs.ts +++ b/src/rules/no-commonjs.ts @@ -4,7 +4,7 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils' -import { createRule } from '../utils' +import { createRule, getScope } from '../utils' type NormalizedOptions = { allowPrimitiveModules?: boolean @@ -122,16 +122,16 @@ export = createRule<[Options?], MessageId>({ // exports. if ('name' in node.object && node.object.name === 'exports') { - const isInScope = context - .getScope() - .variables.some(variable => variable.name === 'exports') + const isInScope = getScope(context, node).variables.some( + variable => variable.name === 'exports', + ) if (!isInScope) { context.report({ node, messageId: 'export' }) } } }, CallExpression(call) { - if (!validateScope(context.getScope())) { + if (!validateScope(getScope(context, call))) { return } diff --git a/src/rules/no-cycle.ts b/src/rules/no-cycle.ts index c61f86b90..edbf03fcd 100644 --- a/src/rules/no-cycle.ts +++ b/src/rules/no-cycle.ts @@ -2,6 +2,8 @@ * Ensures that no imported module imports the linted module. */ +import { getPhysicalFilename } from 'eslint-compat-utils' + import type { DeclarationMetadata, ModuleOptions } from '../utils' import { ExportMap, @@ -70,9 +72,7 @@ export = createRule<[Options?], MessageId>({ }, defaultOptions: [], create(context) { - const filename = context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename() + const filename = getPhysicalFilename(context) if (filename === '') { return {} diff --git a/src/rules/no-default-export.ts b/src/rules/no-default-export.ts index 18773938e..f102ae350 100644 --- a/src/rules/no-default-export.ts +++ b/src/rules/no-default-export.ts @@ -1,3 +1,5 @@ +import { getSourceCode } from 'eslint-compat-utils' + import { createRule } from '../utils' export = createRule({ @@ -24,7 +26,7 @@ export = createRule({ return { ExportDefaultDeclaration(node) { - const { loc } = context.getSourceCode().getFirstTokens(node)[1] || {} + const { loc } = getSourceCode(context).getFirstTokens(node)[1] || {} context.report({ node, messageId: 'preferNamed', @@ -39,7 +41,7 @@ export = createRule({ ('value' in specifier.exported && specifier.exported.value)) === 'default', )) { - const { loc } = context.getSourceCode().getFirstTokens(node)[1] || {} + const { loc } = getSourceCode(context).getFirstTokens(node)[1] || {} // @ts-expect-error - legacy parser type if (specifier.type === 'ExportDefaultSpecifier') { context.report({ diff --git a/src/rules/no-deprecated.ts b/src/rules/no-deprecated.ts index adcb1c93a..891f93cfd 100644 --- a/src/rules/no-deprecated.ts +++ b/src/rules/no-deprecated.ts @@ -148,7 +148,7 @@ export = createRule({ return } - if (declaredScope(context, node.name) !== 'module') { + if (declaredScope(context, node, node.name) !== 'module') { return } context.report({ @@ -165,7 +165,10 @@ export = createRule({ return } - if (declaredScope(context, dereference.object.name) !== 'module') { + if ( + declaredScope(context, dereference, dereference.object.name) !== + 'module' + ) { return } diff --git a/src/rules/no-duplicates.ts b/src/rules/no-duplicates.ts index ef1dd77de..9f54df99a 100644 --- a/src/rules/no-duplicates.ts +++ b/src/rules/no-duplicates.ts @@ -1,4 +1,5 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils' +import { getSourceCode } from 'eslint-compat-utils' import semver from 'semver' import type { PackageJson } from 'type-fest' @@ -28,7 +29,7 @@ function checkImports( for (const [module, nodes] of imported.entries()) { if (nodes.length > 1) { const [first, ...rest] = nodes - const sourceCode = context.getSourceCode() + const sourceCode = getSourceCode(context) const fix = getFix(first, rest, sourceCode, context) context.report({ diff --git a/src/rules/no-empty-named-blocks.ts b/src/rules/no-empty-named-blocks.ts index 17f18170b..5322188d5 100644 --- a/src/rules/no-empty-named-blocks.ts +++ b/src/rules/no-empty-named-blocks.ts @@ -1,4 +1,5 @@ import type { TSESTree } from '@typescript-eslint/utils' +import { getSourceCode } from 'eslint-compat-utils' import { createRule } from '../utils' @@ -103,7 +104,7 @@ export = createRule({ fix(fixer) { // Remove the empty block and the 'from' token, leaving the import only for its side // effects, e.g. `import 'mod'` - const sourceCode = context.getSourceCode() + const sourceCode = getSourceCode(context) const fromToken = pTokens.find(t => t.value === 'from')! const importToken = pTokens.find( t => t.value === 'import', diff --git a/src/rules/no-extraneous-dependencies.ts b/src/rules/no-extraneous-dependencies.ts index dd02954f0..7165f440d 100644 --- a/src/rules/no-extraneous-dependencies.ts +++ b/src/rules/no-extraneous-dependencies.ts @@ -2,6 +2,7 @@ import fs from 'node:fs' import path from 'node:path' import type { TSESTree } from '@typescript-eslint/utils' +import { getPhysicalFilename } from 'eslint-compat-utils' import { minimatch } from 'minimatch' import type { PackageJson } from 'type-fest' @@ -92,9 +93,7 @@ function getDependencies(context: RuleContext, packageDir?: string | string[]) { } else { // use closest package.json const packageJsonPath = pkgUp({ - cwd: context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename(), + cwd: getPhysicalFilename(context), })! const packageContent_ = getPackageDepFields(packageJsonPath, false) @@ -383,9 +382,7 @@ export = createRule<[Options?], MessageId>({ create(context) { const options = context.options[0] || {} - const filename = context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename() + const filename = getPhysicalFilename(context) const deps = getDependencies(context, options.packageDir) || extractDepFields({}) diff --git a/src/rules/no-import-module-exports.ts b/src/rules/no-import-module-exports.ts index 7ce8af43d..13aebab79 100644 --- a/src/rules/no-import-module-exports.ts +++ b/src/rules/no-import-module-exports.ts @@ -1,6 +1,7 @@ import path from 'node:path' import type { TSESLint, TSESTree } from '@typescript-eslint/utils' +import { getPhysicalFilename, getSourceCode } from 'eslint-compat-utils' import { minimatch } from 'minimatch' import type { RuleContext } from '../types' @@ -8,9 +9,7 @@ import { createRule, pkgUp } from '../utils' function getEntryPoint(context: RuleContext) { const pkgPath = pkgUp({ - cwd: context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename(), + cwd: getPhysicalFilename(context), })! try { return require.resolve(path.dirname(pkgPath)) @@ -22,7 +21,7 @@ function getEntryPoint(context: RuleContext) { } function findScope(context: RuleContext, identifier: string) { - const { scopeManager } = context.getSourceCode() + const { scopeManager } = getSourceCode(context) return ( scopeManager?.scopes // eslint-disable-next-line unicorn/prefer-spread @@ -92,9 +91,7 @@ export = createRule<[Options?], MessageId>({ return } - const fileName = context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename() + const fileName = getPhysicalFilename(context) const isEntryPoint = entryPoint === fileName const isIdentifier = node.object.type === 'Identifier' diff --git a/src/rules/no-mutable-exports.ts b/src/rules/no-mutable-exports.ts index 83b36e71e..d6e52b39c 100644 --- a/src/rules/no-mutable-exports.ts +++ b/src/rules/no-mutable-exports.ts @@ -1,6 +1,6 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils' -import { createRule } from '../utils' +import { createRule, getScope } from '../utils' type MessageId = 'noMutable' @@ -48,14 +48,14 @@ export = createRule<[], MessageId>({ return { ExportDefaultDeclaration(node) { - const scope = context.getScope() + const scope = getScope(context, node) if ('name' in node.declaration) { checkDeclarationsInScope(scope, node.declaration.name) } }, ExportNamedDeclaration(node) { - const scope = context.getScope() + const scope = getScope(context, node) if (node.declaration) { checkDeclaration(node.declaration) diff --git a/src/rules/no-named-as-default-member.ts b/src/rules/no-named-as-default-member.ts index e9557cb0c..10adb7ca6 100644 --- a/src/rules/no-named-as-default-member.ts +++ b/src/rules/no-named-as-default-member.ts @@ -45,7 +45,7 @@ export = createRule<[], MessageId>({ return { ImportDefaultSpecifier(node) { - const declaration = importDeclaration(context) + const declaration = importDeclaration(context, node) const exportMap = ExportMap.get(declaration.source.value, context) if (exportMap == null) { return diff --git a/src/rules/no-named-as-default.ts b/src/rules/no-named-as-default.ts index 6c44e0890..7d6697a4e 100644 --- a/src/rules/no-named-as-default.ts +++ b/src/rules/no-named-as-default.ts @@ -34,7 +34,7 @@ export = createRule<[], MessageId>({ return } - const declaration = importDeclaration(context) + const declaration = importDeclaration(context, defaultSpecifier) const imports = ExportMap.get(declaration.source.value, context) if (imports == null) { diff --git a/src/rules/no-namespace.ts b/src/rules/no-namespace.ts index 69eba7697..095cc6746 100644 --- a/src/rules/no-namespace.ts +++ b/src/rules/no-namespace.ts @@ -3,9 +3,10 @@ */ import type { TSESLint, TSESTree } from '@typescript-eslint/utils' +import { getSourceCode } from 'eslint-compat-utils' import { minimatch } from 'minimatch' -import { createRule } from '../utils' +import { createRule, getScope } from '../utils' type MessageId = 'noNamespace' @@ -59,7 +60,7 @@ export = createRule<[Options?], MessageId>({ return } - const scopeVariables = context.getScope().variables + const scopeVariables = getScope(context, node).variables const namespaceVariable = scopeVariables.find( variable => variable.defs[0].node === node, )! @@ -76,7 +77,7 @@ export = createRule<[Options?], MessageId>({ messageId: `noNamespace`, fix: canFix ? fixer => { - const scopeManager = context.getSourceCode().scopeManager! + const scopeManager = getSourceCode(context).scopeManager! const fixes: TSESLint.RuleFix[] = [] // Pass 1: Collect variable names that are already in scope for each reference we want diff --git a/src/rules/no-relative-packages.ts b/src/rules/no-relative-packages.ts index 69a43a35d..9e23e6f26 100644 --- a/src/rules/no-relative-packages.ts +++ b/src/rules/no-relative-packages.ts @@ -1,6 +1,7 @@ import path from 'node:path' import type { TSESTree } from '@typescript-eslint/utils' +import { getPhysicalFilename } from 'eslint-compat-utils' import type { RuleContext } from '../types' import type { ModuleOptions } from '../utils' @@ -39,9 +40,7 @@ function checkImportForRelativePackage( } const resolvedImport = resolve(importPath, context) - const resolvedContext = context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename() + const resolvedContext = getPhysicalFilename(context) if (!resolvedImport || !resolvedContext) { return diff --git a/src/rules/no-relative-parent-imports.ts b/src/rules/no-relative-parent-imports.ts index 5fbe4a513..8b066fca7 100644 --- a/src/rules/no-relative-parent-imports.ts +++ b/src/rules/no-relative-parent-imports.ts @@ -1,5 +1,7 @@ import path from 'node:path' +import { getPhysicalFilename } from 'eslint-compat-utils' + import type { ModuleOptions } from '../utils' import { importType, @@ -27,9 +29,7 @@ export = createRule<[ModuleOptions?], MessageId>({ }, defaultOptions: [], create(context) { - const filename = context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename() + const filename = getPhysicalFilename(context) if (filename === '') { return {} diff --git a/src/rules/no-restricted-paths.ts b/src/rules/no-restricted-paths.ts index 2548bc39b..31c30fd4f 100644 --- a/src/rules/no-restricted-paths.ts +++ b/src/rules/no-restricted-paths.ts @@ -1,6 +1,7 @@ import path from 'node:path' import type { TSESTree } from '@typescript-eslint/utils' +import { getPhysicalFilename } from 'eslint-compat-utils' import isGlob from 'is-glob' import { Minimatch } from 'minimatch' @@ -116,9 +117,7 @@ export = createRule<[Options?], MessageId>({ const options = context.options[0] || {} const restrictedPaths = options.zones || [] const basePath = options.basePath || process.cwd() - const currentFilename = context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename() + const currentFilename = getPhysicalFilename(context) const matchingZones = restrictedPaths.filter(zone => [zone.target] .flat() diff --git a/src/rules/no-self-import.ts b/src/rules/no-self-import.ts index 932844611..63ddca5f4 100644 --- a/src/rules/no-self-import.ts +++ b/src/rules/no-self-import.ts @@ -3,6 +3,7 @@ */ import type { TSESTree } from '@typescript-eslint/utils' +import { getPhysicalFilename } from 'eslint-compat-utils' import type { RuleContext } from '../types' import { createRule, moduleVisitor, resolve } from '../utils' @@ -14,9 +15,7 @@ function isImportingSelf( node: TSESTree.Node, requireName: string, ) { - const filePath = context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename() + const filePath = getPhysicalFilename(context) // If the input is from stdin, this test can't fail if (filePath !== '' && filePath === resolve(requireName, context)) { diff --git a/src/rules/no-unassigned-import.ts b/src/rules/no-unassigned-import.ts index a3c96c00c..9f86415b7 100644 --- a/src/rules/no-unassigned-import.ts +++ b/src/rules/no-unassigned-import.ts @@ -1,5 +1,6 @@ import path from 'node:path' +import { getPhysicalFilename } from 'eslint-compat-utils' import { minimatch } from 'minimatch' import { isStaticRequire, createRule } from '../utils' @@ -64,9 +65,7 @@ export = createRule<[Options?], MessageId>({ create(context) { const options = context.options[0] || {} - const filename = context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename() + const filename = getPhysicalFilename(context) const isAllow = (source: string) => testIsAllow(options.allow, filename, source) diff --git a/src/rules/no-unused-modules.ts b/src/rules/no-unused-modules.ts index 4112f2086..38a9faad8 100644 --- a/src/rules/no-unused-modules.ts +++ b/src/rules/no-unused-modules.ts @@ -6,6 +6,7 @@ import path from 'node:path' import { TSESTree } from '@typescript-eslint/utils' +import { getPhysicalFilename } from 'eslint-compat-utils' import type { FileExtension, RuleContext } from '../types' import { @@ -485,9 +486,7 @@ export = createRule({ doPreparation(src, ignoreExports, context) } - const file = context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename() + const file = getPhysicalFilename(context) const checkExportPresence = (node: TSESTree.Program) => { if (!missingExports) { diff --git a/src/rules/no-useless-path-segments.ts b/src/rules/no-useless-path-segments.ts index 1632dd746..521a28453 100644 --- a/src/rules/no-useless-path-segments.ts +++ b/src/rules/no-useless-path-segments.ts @@ -4,6 +4,8 @@ import path from 'node:path' +import { getPhysicalFilename } from 'eslint-compat-utils' + import type { ModuleOptions } from '../utils' import { createRule, moduleVisitor, resolve, getFileExtensions } from '../utils' @@ -67,11 +69,7 @@ export = createRule<[Options?], MessageId>({ }, defaultOptions: [], create(context) { - const currentDir = path.dirname( - context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename(), - ) + const currentDir = path.dirname(getPhysicalFilename(context)) const options = context.options[0] || {} diff --git a/src/rules/order.ts b/src/rules/order.ts index a77abebd4..e97bae669 100644 --- a/src/rules/order.ts +++ b/src/rules/order.ts @@ -1,4 +1,5 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils' +import { getSourceCode } from 'eslint-compat-utils' import { minimatch } from 'minimatch' import type { MinimatchOptions } from 'minimatch' @@ -305,7 +306,7 @@ function fixOutOfOrder( secondNode: ImportEntryWithRank, order: 'before' | 'after', ) { - const sourceCode = context.getSourceCode() + const sourceCode = getSourceCode(context) const firstRoot = findRootNode(firstNode.node) const firstRootStart = findStartOfLineWithComments(sourceCode, firstRoot) @@ -703,7 +704,7 @@ function fixNewLineAfterImport( ) { const prevRoot = findRootNode(previousImport.node) const tokensToEndOfLine = takeTokensAfterWhile( - context.getSourceCode(), + getSourceCode(context), prevRoot, commentOnSameLineAs(prevRoot), ) @@ -721,7 +722,7 @@ function removeNewLineAfterImport( currentImport: ImportEntry, previousImport: ImportEntry, ) { - const sourceCode = context.getSourceCode() + const sourceCode = getSourceCode(context) const prevRoot = findRootNode(previousImport.node) const currRoot = findRootNode(currentImport.node) const rangeToRemove = [ @@ -1017,7 +1018,7 @@ export = createRule<[Options?], MessageId>({ type = 'import' } else { value = '' - displayName = context.getSourceCode().getText(node.moduleReference) + displayName = getSourceCode(context).getText(node.moduleReference) type = 'import:object' } registerNode( diff --git a/src/utils/declared-scope.ts b/src/utils/declared-scope.ts index a3a55be2c..b27f7f40e 100644 --- a/src/utils/declared-scope.ts +++ b/src/utils/declared-scope.ts @@ -1,7 +1,15 @@ +import type { TSESTree } from '@typescript-eslint/utils' + import type { RuleContext } from '../types' -export function declaredScope(context: RuleContext, name: string) { - const references = context.getScope().references +import { getScope } from './get-scope' + +export function declaredScope( + context: RuleContext, + node: TSESTree.Node, + name: string, +) { + const references = getScope(context, node).references const reference = references.find(x => x.identifier.name === name) if (!reference || !reference.resolved) { return diff --git a/src/utils/get-ancestors.ts b/src/utils/get-ancestors.ts new file mode 100644 index 000000000..285a0d2d3 --- /dev/null +++ b/src/utils/get-ancestors.ts @@ -0,0 +1,13 @@ +import type { TSESTree } from '@typescript-eslint/utils' +import { getSourceCode } from 'eslint-compat-utils' + +import type { RuleContext } from '../types' + +export const getAncestors = ( + context: RuleContext, + node: TSESTree.Node | TSESTree.Token, +) => { + const sourceCode = getSourceCode(context) + // @ts-expect-error - eslint v9 + return sourceCode.getAncestors(node) as TSESTree.Node[] +} diff --git a/src/utils/get-scope.ts b/src/utils/get-scope.ts new file mode 100644 index 000000000..7a646d8a3 --- /dev/null +++ b/src/utils/get-scope.ts @@ -0,0 +1,13 @@ +import type { TSESLint, TSESTree } from '@typescript-eslint/utils' +import { getSourceCode } from 'eslint-compat-utils' + +import type { RuleContext } from '../types' + +export const getScope = ( + context: RuleContext, + node: TSESTree.Node | TSESTree.Token, +) => { + const sourceCode = getSourceCode(context) + // @ts-expect-error - eslint v9 + return sourceCode.getScope(node) as TSESLint.Scope.Scope +} diff --git a/src/utils/import-declaration.ts b/src/utils/import-declaration.ts index 842120709..3795ef7e1 100644 --- a/src/utils/import-declaration.ts +++ b/src/utils/import-declaration.ts @@ -2,7 +2,12 @@ import type { TSESTree } from '@typescript-eslint/utils' import type { RuleContext } from '../types' -export const importDeclaration = (context: RuleContext) => { - const ancestors = context.getAncestors() +import { getAncestors } from './get-ancestors' + +export const importDeclaration = ( + context: RuleContext, + node: TSESTree.Node, +) => { + const ancestors = getAncestors(context, node) return ancestors[ancestors.length - 1] as TSESTree.ImportDeclaration } diff --git a/src/utils/index.ts b/src/utils/index.ts index e76327a63..5bf801688 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -3,6 +3,8 @@ export * from './create-rule' export * from './declared-scope' export * from './docs-url' export * from './export-map' +export * from './get-ancestors' +export * from './get-scope' export * from './hash' export * from './ignore' export * from './import-declaration' diff --git a/src/utils/package-path.ts b/src/utils/package-path.ts index ceba8bebb..960514df3 100644 --- a/src/utils/package-path.ts +++ b/src/utils/package-path.ts @@ -1,16 +1,14 @@ import path from 'node:path' +import { getPhysicalFilename } from 'eslint-compat-utils' + import type { RuleContext } from '../types' import { pkgUp } from './pkg-up' import { readPkgUp } from './read-pkg-up' export function getContextPackagePath(context: RuleContext) { - return getFilePackagePath( - context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename(), - ) + return getFilePackagePath(getPhysicalFilename(context)) } export function getFilePackagePath(filePath: string) { diff --git a/src/utils/resolve.ts b/src/utils/resolve.ts index 430e35c09..e6783dc45 100644 --- a/src/utils/resolve.ts +++ b/src/utils/resolve.ts @@ -2,6 +2,8 @@ import fs from 'node:fs' import { createRequire } from 'node:module' import path from 'node:path' +import { getPhysicalFilename } from 'eslint-compat-utils' + import type { Arrayable, ImportResolver, @@ -287,13 +289,7 @@ const erroredContexts = new Set() */ export function resolve(p: string, context: RuleContext) { try { - return relative( - p, - context.getPhysicalFilename - ? context.getPhysicalFilename() - : context.getFilename(), - context.settings, - ) + return relative(p, getPhysicalFilename(context), context.settings) } catch (error_) { const error = error_ as Error if (!erroredContexts.has(context)) { diff --git a/yarn.lock b/yarn.lock index 36ec25119..b033a1e2c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3338,6 +3338,13 @@ eslint-compat-utils@^0.1.2: resolved "https://registry.yarnpkg.com/eslint-compat-utils/-/eslint-compat-utils-0.1.2.tgz#f45e3b5ced4c746c127cf724fb074cd4e730d653" integrity sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg== +eslint-compat-utils@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/eslint-compat-utils/-/eslint-compat-utils-0.5.0.tgz#f7b2eb2befec25a370fac76934d3f9189f312a65" + integrity sha512-dc6Y8tzEcSYZMHa+CMPLi/hyo1FzNeonbhJL7Ol0ccuKQkwopJcJBA9YL/xmMTLU1eKigXo9vj9nALElWYSowg== + dependencies: + semver "^7.5.4" + eslint-config-prettier@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f"