Skip to content

Commit

Permalink
[utils] [new] add context compatibility helpers
Browse files Browse the repository at this point in the history
This change adds helper functions to `eslint-module-utils` in order to add eslint v9 support to `eslint-plugin-import` in a backwards compatible way.

Contributes to import-js#2996
  • Loading branch information
michaelfaith authored and sparten11740 committed Nov 21, 2024
1 parent 55add49 commit dd58fd6
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 1 deletion.
4 changes: 4 additions & 0 deletions utils/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange

## Unreleased

### New
- add context compatibility helpers ([#3049], thanks [@michaelfaith])

## v2.9.0 - 2024-09-02

### New
Expand Down Expand Up @@ -155,6 +158,7 @@ Yanked due to critical issue with cache key resulting from #839.
### Fixed
- `unambiguous.test()` regex is now properly in multiline mode

[#3049]: https://github.com/import-js/eslint-plugin-import/pull/3049
[#3039]: https://github.com/import-js/eslint-plugin-import/pull/3039
[#3018]: https://github.com/import-js/eslint-plugin-import/pull/3018
[#2963]: https://github.com/import-js/eslint-plugin-import/pull/2963
Expand Down
38 changes: 38 additions & 0 deletions utils/contextCompat.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Scope, SourceCode, Rule } from 'eslint';
import * as ESTree from 'estree';

type LegacyContext = {
getFilename: () => string,
getPhysicalFilename: () => string,
getSourceCode: () => SourceCode,
getScope: never,
getAncestors: never,
getDeclaredVariables: never,
};

type NewContext = {
filename: string,
sourceCode: SourceCode,
getPhysicalFilename?: () => string,
getScope: () => Scope.Scope,
getAncestors: () => ESTree.Node[],
getDeclaredVariables: (node: ESTree.Node) => Scope.Variable[],
};

export type Context = LegacyContext | NewContext | Rule.RuleContext;

declare function getAncestors(context: Context, node: ESTree.Node): ESTree.Node[];
declare function getDeclaredVariables(context: Context, node: ESTree.Node): Scope.Variable[];
declare function getFilename(context: Context): string;
declare function getPhysicalFilename(context: Context): string;
declare function getScope(context: Context, node: ESTree.Node): Scope.Scope;
declare function getSourceCode(context: Context): SourceCode;

export {
getAncestors,
getDeclaredVariables,
getFilename,
getPhysicalFilename,
getScope,
getSourceCode,
};
72 changes: 72 additions & 0 deletions utils/contextCompat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
'use strict';

exports.__esModule = true;

/** @type {import('./contextCompat').getAncestors} */
function getAncestors(context, node) {
const sourceCode = getSourceCode(context);

if (sourceCode && sourceCode.getAncestors) {
return sourceCode.getAncestors(node);
}

return context.getAncestors();
}

/** @type {import('./contextCompat').getDeclaredVariables} */
function getDeclaredVariables(context, node) {
const sourceCode = getSourceCode(context);

if (sourceCode && sourceCode.getDeclaredVariables) {
return sourceCode.getDeclaredVariables(node);
}

return context.getDeclaredVariables(node);
}

/** @type {import('./contextCompat').getFilename} */
function getFilename(context) {
if ('filename' in context) {
return context.filename;
}

return context.getFilename();
}

/** @type {import('./contextCompat').getPhysicalFilename} */
function getPhysicalFilename(context) {
if (context.getPhysicalFilename) {
return context.getPhysicalFilename();
}

return getFilename(context);
}

/** @type {import('./contextCompat').getScope} */
function getScope(context, node) {
const sourceCode = getSourceCode(context);

if (sourceCode && sourceCode.getScope) {
return sourceCode.getScope(node);
}

return context.getScope();
}

/** @type {import('./contextCompat').getSourceCode} */
function getSourceCode(context) {
if ('sourceCode' in context) {
return context.sourceCode;
}

return context.getSourceCode();
}

module.exports = {
getAncestors,
getDeclaredVariables,
getFilename,
getPhysicalFilename,
getScope,
getSourceCode,
};
1 change: 1 addition & 0 deletions utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
},
"main": false,
"exports": {
"./contextCompat": "./contextCompat.js",
"./ModuleCache": "./ModuleCache.js",
"./ModuleCache.js": "./ModuleCache.js",
"./declaredScope": "./declaredScope.js",
Expand Down
3 changes: 2 additions & 1 deletion utils/resolve.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ exports.__esModule = true;
const fs = require('fs');
const Module = require('module');
const path = require('path');
const { getPhysicalFilename } = require('./contextCompat');

const hashObject = require('./hash').hashObject;
const ModuleCache = require('./ModuleCache').default;
Expand Down Expand Up @@ -229,7 +230,7 @@ const erroredContexts = new Set();
*/
function resolve(p, context) {
try {
return relative(p, context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename(), context.settings);
return relative(p, getPhysicalFilename(context), context.settings);
} catch (err) {
if (!erroredContexts.has(context)) {
// The `err.stack` string starts with `err.name` followed by colon and `err.message`.
Expand Down

0 comments on commit dd58fd6

Please # to comment.