Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: bump ESLint, NodeJS, and TS minimum version requirements #8377

Merged
merged 11 commits into from Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/prepare-build/action.yml
Expand Up @@ -6,7 +6,7 @@ description: 'Prepares the repo for a job by running the build'
runs:
using: 'composite'
steps:
- uses: actions/cache@v3
- uses: actions/cache@v4
id: build-cache
with:
path: '**/dist/**'
Expand Down
6 changes: 3 additions & 3 deletions .github/actions/prepare-install/action.yml
Expand Up @@ -31,7 +31,7 @@ runs:
run: echo ${{ github.ref }}

- name: Use Node.js ${{ inputs.node-version }}
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
registry-url: ${{ inputs.registry-url }}
Expand All @@ -47,7 +47,7 @@ runs:
# Yarn rotates the downloaded cache archives, @see https://github.com/actions/setup-node/issues/325
# Yarn cache is also reusable between arch and os.
- name: Restore yarn cache
uses: actions/cache@v3
uses: actions/cache@v4
id: yarn-download-cache
with:
path: ${{ steps.yarn-config.outputs.CACHE_FOLDER }}
Expand All @@ -58,7 +58,7 @@ runs:
# Invalidated on yarn.lock changes
- name: Restore yarn install state
id: yarn-install-state-cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: .yarn/ci-cache/
key: ${{ runner.os }}-yarn-install-state-cache-${{ hashFiles('yarn.lock', '.yarnrc.yml') }}
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/wait-for-netlify/action.yml
Expand Up @@ -11,5 +11,5 @@ inputs:
description: How long to wait between retries of the Netlify api

runs:
using: node16
using: node20
main: index.js
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Expand Up @@ -156,10 +156,10 @@ jobs:
matrix:
exclude:
- os: windows-latest
node-version: 16
node-version: 18
os: [ubuntu-latest, windows-latest]
# just run on the oldest and latest supported versions and assume the intermediate versions are good
node-version: [16, 20]
node-version: [18, 20]
package:
[
'ast-spec',
Expand Down
Expand Up @@ -116,6 +116,7 @@ A single PR can remove support for old TypeScript versions as a breaking change:
1. Update the `SUPPORTED_TYPESCRIPT_VERSIONS` constant in `warnAboutTSVersion.ts`
1. Update the `versions` constant in `version-check.ts`
1. Update [Users > Dependency Versions > TypeScript](../../users/Dependency_Versions.mdx#typescript)
1. Update `MIN_TS_VERSION_SEMVER` in `packages/website/src/components/OptionsSelector.tsx`
1. Search for source code comments (excluding `CHANGELOG.md` files) that mention a now-unsupported version of TypeScript.
- For example, to remove support for v4.3, searches might include:
- `4.3`
Expand Down
20 changes: 16 additions & 4 deletions docs/users/Dependency_Versions.mdx
Expand Up @@ -7,13 +7,25 @@ import packageJson from '../../package.json';

## ESLint

> The version range of ESLint currently supported is `^7.0.0 || ^8.0.0`.
<blockquote>
<p>
The version range of ESLint currently supported is{' '}
<code>{packageJson.devDependencies.eslint}</code>.
</p>
</blockquote>

We generally support at least the latest two major versions of ESLint.
We generally support at least the latest two major versions of ESLint; though sometimes we may restrict this if the APIs change too much between major releases.

## Node

This project makes an effort to support Active LTS and Maintenance LTS release statuses of Node according to [Node's release document](https://github.com/nodejs/release#release-schedule).
<blockquote>
<p>
The version range of NodeJS currently supported is{' '}
<code>{packageJson.engines.node}</code>.
</p>
</blockquote>

We make an effort to support Active LTS and Maintenance LTS release statuses of Node according to [Node's release document](https://github.com/nodejs/release#release-schedule).
Support for specific Current status releases are considered periodically.

## TypeScript
Expand All @@ -25,7 +37,7 @@ Support for specific Current status releases are considered periodically.
</p>
</blockquote>

Note that we mirror [DefinitelyTyped's version support window](https://github.com/DefinitelyTyped/DefinitelyTyped/#support-window) - meaning we only support versions of TypeScript less than 2 years old.
We mirror [DefinitelyTyped's version support window](https://github.com/DefinitelyTyped/DefinitelyTyped/#support-window) - meaning we only support versions of TypeScript less than 2 years old.

You may find that our tooling works on older TypeScript versions however we provide no guarantees and **_we will not accept issues against unsupported versions_**.

Expand Down
8 changes: 4 additions & 4 deletions package.json
Expand Up @@ -50,7 +50,7 @@
"typecheck": "npx nx run-many --target=typecheck --parallel"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
"node": "^18.18.0 || >=20.0.0"
},
"devDependencies": {
"@actions/core": "^1.10.0",
Expand All @@ -63,7 +63,6 @@
"@nx/eslint": "17.2.8",
"@nx/jest": "17.2.8",
"@nx/workspace": "17.2.8",
"@prettier/sync": "^0.5.0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

heck yes async everywhere

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

everywhere except eslint-plugin-internal. One day we'll have async plugins . . . .

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙏

"@swc/core": "^1.3.68",
"@swc/jest": "^0.2.26",
"@types/babel__code-frame": "^7.0.3",
Expand All @@ -84,7 +83,7 @@
"cross-fetch": "^4.0.0",
"cspell": "^7.0.0",
"downlevel-dts": ">=0.11.0",
"eslint": "^8.56.0",
"eslint": "8.56.0",
"eslint-plugin-deprecation": "^2.0.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-eslint-plugin": "^5.2.1",
Expand Down Expand Up @@ -117,7 +116,7 @@
"ts-node": "10.7.0",
"tslint": "^6.1.3",
"tsx": "^4.6.2",
"typescript": ">=4.3.5 <5.4.0",
"typescript": ">=4.7.4 <5.4.0",
"typescript-eslint": "workspace:^",
"yargs": "17.7.2"
},
Expand All @@ -139,6 +138,7 @@
"@types/estree": "link:./tools/dummypkg",
"@types/node": "^20.0.0",
"@types/react": "^18.2.14",
"eslint": "8.56.0",
"eslint-visitor-keys": "^3.4.1",
"jest-config": "^29",
"jest-resolve": "^29",
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin-internal/package.json
Expand Up @@ -13,7 +13,7 @@
"typecheck": "tsc -p tsconfig.json --noEmit"
},
"dependencies": {
"@prettier/sync": "*",
"@prettier/sync": "^0.5.0",
"@typescript-eslint/rule-tester": "6.21.0",
"@typescript-eslint/scope-manager": "6.21.0",
"@typescript-eslint/type-utils": "6.21.0",
Expand Down
Expand Up @@ -2,7 +2,6 @@ import prettier from '@prettier/sync';
import { getContextualType } from '@typescript-eslint/type-utils';
import type { TSESTree } from '@typescript-eslint/utils';
import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils';
import { getSourceCode } from '@typescript-eslint/utils/eslint-utils';

import { createRule } from '../util';

Expand Down Expand Up @@ -148,7 +147,6 @@ export default createRule<Options, MessageIds>({
},
],
create(context, [{ formatWithPrettier }]) {
const sourceCode = getSourceCode(context);
const services = ESLintUtils.getParserServices(context);
const checker = services.program.getTypeChecker();

Expand Down Expand Up @@ -326,7 +324,10 @@ export default createRule<Options, MessageIds>({
});
}

const parentIndent = getExpectedIndentForNode(literal, sourceCode.lines);
const parentIndent = getExpectedIndentForNode(
literal,
context.sourceCode.lines,
);
if (lastLine.length !== parentIndent) {
return context.report({
node: literal,
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin-tslint/package.json
Expand Up @@ -49,7 +49,7 @@
"@typescript-eslint/utils": "6.21.0"
},
"peerDependencies": {
"eslint": "^7.0.0 || ^8.0.0",
"eslint": "^8.56.0",
"tslint": "^5.0.0 || ^6.0.0",
"typescript": "*"
},
Expand Down
10 changes: 2 additions & 8 deletions packages/eslint-plugin-tslint/src/rules/config.ts
@@ -1,9 +1,4 @@
import { ESLintUtils } from '@typescript-eslint/utils';
import {
getCwd,
getFilename,
getSourceCode,
} from '@typescript-eslint/utils/eslint-utils';
import path from 'path';
import type { RuleSeverity } from 'tslint';
import { Configuration } from 'tslint';
Expand Down Expand Up @@ -124,8 +119,7 @@ export default createRule<Options, MessageIds>({
context,
[{ rules: tslintRules, rulesDirectory: tslintRulesDirectory, lintFile }],
) {
const fileName = path.resolve(getCwd(context), getFilename(context));
const sourceCode = getSourceCode(context).text;
const fileName = path.resolve(context.cwd, context.filename);
const services = ESLintUtils.getParserServices(context);
const program = services.program;

Expand All @@ -144,7 +138,7 @@ export default createRule<Options, MessageIds>({
tslintRules,
tslintRulesDirectory,
);
tslint.lint(fileName, sourceCode, configuration);
tslint.lint(fileName, context.sourceCode.text, configuration);

const result = tslint.getResult();

Expand Down
9 changes: 5 additions & 4 deletions packages/eslint-plugin/package.json
Expand Up @@ -51,8 +51,8 @@
"generate:breaking-changes": "yarn tsx tools/generate-breaking-changes.mts",
"generate:configs": "npx nx run repo-tools:generate-configs",
"lint": "npx nx lint",
"test": "jest --coverage --logHeapUsage",
"test-single": "jest --no-coverage",
"test": "cross-env NODE_OPTIONS=\"--experimental-vm-modules\" jest --coverage --logHeapUsage",
"test-single": "cross-env NODE_OPTIONS=\"--experimental-vm-modules\" jest --no-coverage",
"typecheck": "tsc -p tsconfig.json --noEmit"
},
"dependencies": {
Expand All @@ -69,15 +69,16 @@
"ts-api-utils": "^1.0.1"
},
"devDependencies": {
"@prettier/sync": "*",
"@types/debug": "*",
"@types/marked": "*",
"@types/natural-compare": "*",
"@typescript-eslint/rule-schema-to-typescript-types": "6.21.0",
"@typescript-eslint/rule-tester": "6.21.0",
"ajv": "^6.12.6",
"chalk": "^5.3.0",
"cross-env": "^7.0.3",
"cross-fetch": "*",
"eslint": "*",
"grapheme-splitter": "^1.0.4",
"jest": "29.7.0",
"jest-specific-snapshot": "^8.0.0",
Expand All @@ -92,7 +93,7 @@
},
"peerDependencies": {
"@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
"eslint": "^7.0.0 || ^8.0.0"
"eslint": "^8.56.0"
},
"peerDependenciesMeta": {
"typescript": {
Expand Down
@@ -1,6 +1,5 @@
import type { TSESTree } from '@typescript-eslint/utils';
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
import { getSourceCode } from '@typescript-eslint/utils/eslint-utils';

import { createRule, getNameFromMember, MemberNameType } from '../util';

Expand Down Expand Up @@ -31,8 +30,6 @@ export default createRule({
},
defaultOptions: [],
create(context) {
const sourceCode = getSourceCode(context);

interface Method {
name: string;
static: boolean;
Expand Down Expand Up @@ -74,7 +71,7 @@ export default createRule({
}
case AST_NODE_TYPES.TSMethodSignature:
return {
...getNameFromMember(member, sourceCode),
...getNameFromMember(member, context.sourceCode),
static: isStatic,
callSignature: false,
};
Expand All @@ -94,7 +91,7 @@ export default createRule({
};
case AST_NODE_TYPES.MethodDefinition:
return {
...getNameFromMember(member, sourceCode),
...getNameFromMember(member, context.sourceCode),
static: isStatic,
callSignature: false,
};
Expand Down
7 changes: 2 additions & 5 deletions packages/eslint-plugin/src/rules/array-type.ts
@@ -1,6 +1,5 @@
import type { TSESTree } from '@typescript-eslint/utils';
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
import { getSourceCode } from '@typescript-eslint/utils/eslint-utils';

import { createRule, isParenthesized } from '../util';

Expand Down Expand Up @@ -135,8 +134,6 @@ export default createRule<Options, MessageIds>({
},
],
create(context, [options]) {
const sourceCode = getSourceCode(context);

const defaultOption = options.default;
const readonlyOption = options.readonly ?? defaultOption;

Expand All @@ -145,7 +142,7 @@ export default createRule<Options, MessageIds>({
*/
function getMessageType(node: TSESTree.Node): string {
if (isSimpleType(node)) {
return sourceCode.getText(node);
return context.sourceCode.getText(node);
}
return 'T';
}
Expand Down Expand Up @@ -254,7 +251,7 @@ export default createRule<Options, MessageIds>({
const parentParens =
readonlyPrefix &&
node.parent.type === AST_NODE_TYPES.TSArrayType &&
!isParenthesized(node.parent.elementType, sourceCode);
!isParenthesized(node.parent.elementType, context.sourceCode);

const start = `${parentParens ? '(' : ''}${readonlyPrefix}${
typeParens ? '(' : ''
Expand Down
4 changes: 1 addition & 3 deletions packages/eslint-plugin/src/rules/await-thenable.ts
@@ -1,5 +1,4 @@
import type { TSESLint } from '@typescript-eslint/utils';
import { getSourceCode } from '@typescript-eslint/utils/eslint-utils';
import * as tsutils from 'ts-api-utils';

import {
Expand Down Expand Up @@ -51,9 +50,8 @@ export default createRule({
{
messageId: 'removeAwait',
fix(fixer): TSESLint.RuleFix {
const sourceCode = getSourceCode(context);
const awaitKeyword = nullThrows(
sourceCode.getFirstToken(node, isAwaitKeyword),
context.sourceCode.getFirstToken(node, isAwaitKeyword),
NullThrowsReasons.MissingToken('await', 'await expression'),
);

Expand Down
4 changes: 1 addition & 3 deletions packages/eslint-plugin/src/rules/ban-ts-comment.ts
@@ -1,5 +1,4 @@
import { AST_TOKEN_TYPES, type TSESLint } from '@typescript-eslint/utils';
import { getSourceCode } from '@typescript-eslint/utils/eslint-utils';

import { createRule, getStringLength } from '../util';

Expand Down Expand Up @@ -103,7 +102,6 @@ export default createRule<[Options], MessageIds>({
/^\/*\s*@ts-(?<directive>expect-error|ignore|check|nocheck)(?<description>.*)/;
const commentDirectiveRegExMultiLine =
/^\s*(?:\/|\*)*\s*@ts-(?<directive>expect-error|ignore|check|nocheck)(?<description>.*)/;
const sourceCode = getSourceCode(context);

const descriptionFormats = new Map<string, RegExp>();
for (const directive of [
Expand All @@ -120,7 +118,7 @@ export default createRule<[Options], MessageIds>({

return {
Program(): void {
const comments = sourceCode.getAllComments();
const comments = context.sourceCode.getAllComments();

comments.forEach(comment => {
const regExp =
Expand Down
8 changes: 3 additions & 5 deletions packages/eslint-plugin/src/rules/ban-tslint-comment.ts
@@ -1,5 +1,4 @@
import { AST_TOKEN_TYPES } from '@typescript-eslint/utils';
import { getSourceCode } from '@typescript-eslint/utils/eslint-utils';

import { createRule } from '../util';

Expand Down Expand Up @@ -32,22 +31,21 @@ export default createRule({
},
defaultOptions: [],
create: context => {
const sourceCode = getSourceCode(context);
return {
Program(): void {
const comments = sourceCode.getAllComments();
const comments = context.sourceCode.getAllComments();
comments.forEach(c => {
if (ENABLE_DISABLE_REGEX.test(c.value)) {
context.report({
data: { text: toText(c.value, c.type) },
node: c,
messageId: 'commentDetected',
fix(fixer) {
const rangeStart = sourceCode.getIndexFromLoc({
const rangeStart = context.sourceCode.getIndexFromLoc({
column: c.loc.start.column > 0 ? c.loc.start.column - 1 : 0,
line: c.loc.start.line,
});
const rangeEnd = sourceCode.getIndexFromLoc({
const rangeEnd = context.sourceCode.getIndexFromLoc({
column: c.loc.end.column,
line: c.loc.end.line,
});
Expand Down