Skip to content

Commit

Permalink
feat: eslint 9 support
Browse files Browse the repository at this point in the history
  • Loading branch information
brettz9 committed Jul 2, 2024
1 parent eaaad6a commit 8e111a5
Show file tree
Hide file tree
Showing 10 changed files with 2,522 additions and 6,407 deletions.
50 changes: 50 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { includeIgnoreFile } from '@eslint/compat';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

import eslint from '@eslint/js';
import eslintPlugin from 'eslint-plugin-eslint-plugin';
import eslintConfigPrettier from 'eslint-config-prettier';
import tseslint from 'typescript-eslint';
import globals from 'globals';
import compat from './lib/esm/src/index.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const gitignorePath = path.resolve(__dirname, '.gitignore');

export default [
includeIgnoreFile(gitignorePath),
eslint.configs.recommended,
...tseslint.configs.recommended,
eslintPlugin.configs['flat/recommended'],
compat.configs['flat/recommended'],
eslintConfigPrettier,
{
files: ["**/*.ts", "**/*.js", "**/*.mjs"],
rules: {
'no-template-curly-in-string': ['error'],
'no-console': ['warn']
},
languageOptions: {
globals: {
...globals.jest,
...globals.node
}
}
}
];

/*
parserOptions: {
project: './tsconfig.json'
},
"extends": [
"airbnb-typescript/base",
"plugin:import/typescript",
],
"rules": {
"import/extensions": "off",
"import/no-extraneous-dependencies": "off"
},
*/
8,486 changes: 2,248 additions & 6,238 deletions package-lock.json

Large diffs are not rendered by default.

44 changes: 10 additions & 34 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@
"scripts": {
"benchmarks": "ts-node-transpile-only test/benchmarks.ts",
"build": "rm -rf lib && tsc --project tsconfig.build.json && tsc --project tsconfig.esm.json",
"lint": "eslint --ignore-path .gitignore --ext .js,.ts .",
"lint": "eslint .",
"spec": "jest --testPathIgnorePatterns test/e2e-repo.spec.ts /benchmarks-tmp",
"spec:e2e": "jest test/e2e-repo.spec.ts",
"spec:e2e": "jest --detectOpenHandles test/e2e-repo.spec.ts",
"test": "npm run lint && npm run build && npm run spec",
"tsc": "tsc",
"version": "npm run build"
Expand All @@ -57,27 +57,6 @@
"tabWidth": 2,
"trailingComma": "es5"
},
"eslintConfig": {
"env": {
"jest": true,
"node": true
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"extends": [
"airbnb-typescript/base",
"plugin:eslint-plugin/recommended",
"plugin:import/typescript",
"plugin:prettier/recommended"
],
"rules": {
"import/extensions": "off",
"import/no-extraneous-dependencies": "off"
},
"root": true
},
"jest": {
"preset": "ts-jest",
"testEnvironment": "node",
Expand All @@ -91,33 +70,30 @@
"browserslist": "^4.23.0",
"caniuse-lite": "^1.0.30001605",
"find-up": "^5.0.0",
"globals": "^13.24.0",
"globals": "^15.7.0",
"lodash.memoize": "^4.1.2",
"semver": "^7.6.0"
},
"devDependencies": {
"@babel/core": "^7.24.3",
"@babel/eslint-parser": "^7.24.1",
"@eslint/compat": "^1.1.0",
"@eslint/js": "^9.6.0",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"@tsconfig/node16": "^16.1.3",
"@types/benchmark": "^2.1.5",
"@types/caniuse-lite": "^1.0.5",
"@types/eslint": "^8.56.7",
"@types/eslint": "^8.56.10",
"@types/jest": "^29.5.12",
"@types/lodash.memoize": "^4.1.9",
"@types/semver": "7.5.8",
"@typescript-eslint/eslint-plugin": "^7.5.0",
"@typescript-eslint/parser": "^7.5.0",
"benchmark": "^2.1.4",
"browserslist-config-erb": "^0.0.3",
"electron": "^29.x.x",
"eslint": "^8.57.0",
"eslint-config-airbnb-typescript": "^18.0.0",
"eslint-config-bliss-typescript": "^6.0.2",
"eslint": "^9.6.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-eslint-plugin": "^5.5.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-eslint-plugin": "^6.2.0",
"eslint-plugin-prettier": "^5.1.3",
"expect-type": "^0.19.0",
"jest": "^29.7.0",
Expand All @@ -127,10 +103,10 @@
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
"typescript": "^5.4.3",
"typescript-eslint": "^7.5.0"
"typescript-eslint": "^8.0.0-alpha.36"
},
"peerDependencies": {
"eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
"eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
},
"engines": {
"node": ">=14.x"
Expand Down
21 changes: 18 additions & 3 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import browserslist from "browserslist";
import {
AstMetadataApiWithTargetsResolver,
ESLintNode,
SourceCode,
BrowserListConfig,
Target,
HandleFailingRule,
Expand All @@ -20,8 +21,12 @@ import { TargetNameMappings } from "./constants";
- All of the rules have compatibility info attached to them
- Each API is given to versioning.ts with compatibility info
*/
function isInsideIfStatement(context: Context) {
return context.getAncestors().some((ancestor) => {
function isInsideIfStatement(node: ESLintNode, sourceCode: SourceCode, context: Context) {
const ancestors = 'getAncestors' in sourceCode
// @ts-expect-error Fits
? sourceCode?.getAncestors?.(node)
: context.getAncestors();
return ancestors?.some((ancestor) => {
return ancestor.type === "IfStatement";
});
}
Expand All @@ -30,9 +35,10 @@ function checkNotInsideIfStatementAndReport(
context: Context,
handleFailingRule: HandleFailingRule,
failingRule: AstMetadataApiWithTargetsResolver,
sourceCode: SourceCode,
node: ESLintNode
) {
if (!isInsideIfStatement(context)) {
if (!isInsideIfStatement(node, sourceCode, context)) {
handleFailingRule(failingRule, node);
}
}
Expand All @@ -41,6 +47,7 @@ export function lintCallExpression(
context: Context,
handleFailingRule: HandleFailingRule,
rules: AstMetadataApiWithTargetsResolver[],
sourceCode: SourceCode,
node: ESLintNode
) {
if (!node.callee) return;
Expand All @@ -51,6 +58,7 @@ export function lintCallExpression(
context,
handleFailingRule,
failingRule,
sourceCode,
node
);
}
Expand All @@ -59,6 +67,7 @@ export function lintNewExpression(
context: Context,
handleFailingRule: HandleFailingRule,
rules: Array<AstMetadataApiWithTargetsResolver>,
sourceCode: SourceCode,
node: ESLintNode
) {
if (!node.callee) return;
Expand All @@ -69,6 +78,7 @@ export function lintNewExpression(
context,
handleFailingRule,
failingRule,
sourceCode,
node
);
}
Expand All @@ -77,6 +87,7 @@ export function lintExpressionStatement(
context: Context,
handleFailingRule: HandleFailingRule,
rules: AstMetadataApiWithTargetsResolver[],
sourceCode: SourceCode,
node: ESLintNode
) {
if (!node?.expression?.name) return;
Expand All @@ -88,6 +99,7 @@ export function lintExpressionStatement(
context,
handleFailingRule,
failingRule,
sourceCode,
node
);
}
Expand Down Expand Up @@ -119,6 +131,7 @@ export function lintMemberExpression(
context: Context,
handleFailingRule: HandleFailingRule,
rules: Array<AstMetadataApiWithTargetsResolver>,
sourceCode: SourceCode,
node: ESLintNode
) {
if (!node.object || !node.property) return;
Expand All @@ -142,6 +155,7 @@ export function lintMemberExpression(
context,
handleFailingRule,
failingRule,
sourceCode,
node
);
}
Expand All @@ -158,6 +172,7 @@ export function lintMemberExpression(
context,
handleFailingRule,
failingRule,
sourceCode,
node
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/providers/mdn-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export function isSupportedByMDN(
node: AstMetadataApiWithTargetsResolver,
{ version, target: mdnTarget }: Target
): boolean {
// @ts-ignore
// @ts-expect-error Expected
const target = reversedTargetMappings[mdnTarget];
// If no record could be found, return true. Rules might not
// be found because they could belong to another provider
Expand Down
19 changes: 13 additions & 6 deletions src/rules/compat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function generateErrorName(rule: AstMetadataApiWithTargetsResolver): string {
}

const getPolyfillSet = memoize(
(polyfillArrayJSON: string): Set<String> =>
(polyfillArrayJSON: string): Set<string> =>
new Set(JSON.parse(polyfillArrayJSON))
);

Expand Down Expand Up @@ -89,7 +89,7 @@ const babelConfigs = [
* Determine if a user has a babel config, which we use to infer if the linted code is polyfilled.
*/
function isUsingTranspiler(context: Context): boolean {
const dir = context.getFilename();
const dir = context.filename ?? context.getFilename();
const configPath = findUp.sync(babelConfigs, {
cwd: dir,
});
Expand Down Expand Up @@ -150,6 +150,8 @@ export default {
schema: [{ type: "string" }],
},
create(context: Context): ESLint {
const sourceCode = context.sourceCode ?? context.getSourceCode();

// Determine lowest targets from browserslist config, which reads user's
// package.json config section. Use config from eslintrc for testing purposes
const browserslistConfig: BrowserListConfig =
Expand All @@ -162,6 +164,7 @@ export default {
// @ts-expect-error Checking for accidental misspellings
context.settings.browsersListOpts
) {
// eslint-disable-next-line -- CLI
console.error(
'Please ensure you spell `browserslistOpts` with a lowercase "l"!'
);
Expand Down Expand Up @@ -217,19 +220,22 @@ export default {
null,
context,
handleFailingRule,
targetedRules.CallExpression
targetedRules.CallExpression,
sourceCode
),
NewExpression: lintNewExpression.bind(
null,
context,
handleFailingRule,
targetedRules.NewExpression
targetedRules.NewExpression,
sourceCode
),
ExpressionStatement: lintExpressionStatement.bind(
null,
context,
handleFailingRule,
[...targetedRules.MemberExpression, ...targetedRules.CallExpression]
[...targetedRules.MemberExpression, ...targetedRules.CallExpression],
sourceCode
),
MemberExpression: lintMemberExpression.bind(
null,
Expand All @@ -239,7 +245,8 @@ export default {
...targetedRules.MemberExpression,
...targetedRules.CallExpression,
...targetedRules.NewExpression,
]
],
sourceCode
),
// Keep track of all the defined variables. Do not report errors for nodes that are not defined
Identifier(node: ESLintNode) {
Expand Down
4 changes: 3 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ export type ESLintNode = {
};
};

export type SourceCode = import('eslint').SourceCode;

export interface AstMetadataApiWithTargetsResolver extends AstMetadataApi {
id: string;
caniuseId?: string;
Expand All @@ -70,6 +72,6 @@ export interface Context extends Rule.RuleContext {
browserslistOpts?: BrowsersListOpts;
};
}

// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface BrowsersListOpts
extends Exclude<DefaultBrowsersListOpts, "path"> {}
4 changes: 2 additions & 2 deletions test/benchmarks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ async function getBenchmark(repoInfo: RepoInfo) {

const benchmark = new Benchmark(
name,
(deferred: { resolve: Function }) => {
(deferred: { resolve: () => void }) => {
eslint
.lintFiles(repoInfo.filePatterns)
.then(() => {
Expand Down Expand Up @@ -67,7 +67,7 @@ async function getBenchmark(repoInfo: RepoInfo) {
name: "run",
async: true,
onStart: () => console.log("Starting benchmark suite"),
onComplete: (e) => {
onComplete: (e: Event & {currentTarget: Benchmark[]}) => {
console.log("Finished benchmark suite");
const reports = e.currentTarget.map((benchmark) => ({
name: benchmark.name,
Expand Down
8 changes: 5 additions & 3 deletions test/e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { RuleTester } from "eslint";
import rule from "../src/rules/compat";
import { parser } from 'typescript-eslint';

const ruleTester = new RuleTester({
parserOptions: { ecmaVersion: 2020, sourceType: "module" },
parser: require.resolve("@typescript-eslint/parser"),
languageOptions: {
parser,
parserOptions: { ecmaVersion: 2020, sourceType: "module" },
},
settings: {
lintAllEsApis: true,
},
});

// @ts-ignore
ruleTester.run("compat", rule, {
valid: [
// Ignore ES APIs if config detected
Expand Down
Loading

0 comments on commit 8e111a5

Please sign in to comment.