Skip to content

Commit

Permalink
feat: [4.7] support new extensions (#5027)
Browse files Browse the repository at this point in the history
  • Loading branch information
bradzacher committed May 24, 2022
1 parent 836de79 commit efc147b
Show file tree
Hide file tree
Showing 37 changed files with 186 additions and 125 deletions.
2 changes: 1 addition & 1 deletion .cspell.json
Expand Up @@ -114,7 +114,7 @@
],
"overrides": [
{
"filename": "**/*.{ts,js,tsx,jsx}",
"filename": "**/*.{ts,mts,cts,js,cjs,mjs,tsx,jsx}",
"ignoreRegExpList": ["/@[a-z]+/", "/#(end)?region/"],
"includeRegExpList": [
"/\\/\\*[\\s\\S]*?\\*\\/|([^\\\\:]|^)\\/\\/.*$/",
Expand Down
2 changes: 1 addition & 1 deletion .lintstagedrc
@@ -1,5 +1,5 @@
{
"*.{ts,js,json,md}": [
"*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}": [
"prettier --write"
]
}
12 changes: 8 additions & 4 deletions docs/linting/README.md
Expand Up @@ -85,27 +85,27 @@ With that configured, open a terminal to the root of your project, and run the f
<TabItem value="npm">

```bash
npx eslint . --ext .js,.jsx,.ts,.tsx
npx eslint .
```

</TabItem>
<TabItem value="Yarn">

```bash
yarn eslint . --ext .js,.jsx,.ts,.tsx
yarn eslint .
```

</TabItem>
</Tabs>

That's it - ESLint will lint all `.js`, `.jsx`, `.ts`, and `.tsx` files within the current folder, and will output the results to your terminal.
That's it - ESLint will lint all TypeScript compatible files within the current folder, and will output the results to your terminal.

You are also recommended to add an npm script in your package.json, so you don't have to repeat the same command every time you run ESLint.

```json title="package.json"
{
"scripts": {
"lint": "eslint . --ext .js,.jsx,.ts,.tsx"
"lint": "eslint ."
}
}
```
Expand All @@ -116,6 +116,10 @@ This way, you can invoke the `lint` script directly:
npm run lint
```

:::note
If you use non-standard file extensions, you will need to explicitly tell ESLint to lint those extensions using the [`--ext` flag](https://eslint.org/docs/user-guide/command-line-interface#--ext)
:::

You can also get results in realtime inside most IDEs via a plugin - search your IDE's extension store.

## Next Steps
Expand Down
27 changes: 15 additions & 12 deletions docs/linting/TROUBLESHOOTING.md
Expand Up @@ -119,17 +119,20 @@ As of our v4.0.0 release, this also applies to types.
If you use global types from a 3rd party package (i.e. anything from an `@types` package), then you will have to configure ESLint appropriately to define these global types.
For example; the `JSX` namespace from `@types/react` is a global 3rd party type that you must define in your ESLint config.

Note, that for a mixed project including JavaScript and TypeScript, the `no-undef` rule (like any role) can be turned off for TypeScript files alone by adding an `overrides` section to .eslintrc.json:

```json
"overrides": [
{
"files": ["*.ts"],
"rules": {
"no-undef": "off"
}
}
]
Note, that for a mixed project including JavaScript and TypeScript, the `no-undef` rule (like any rule) can be turned off for TypeScript files alone by adding an `overrides` section to `.eslintrc.cjs`:

```js title=".eslintrc.cjs"
module.exports = {
// ... the rest of your config ...
overrides: [
{
files: ['*.ts', '*.mts', '*.cts', '*.tsx'],
rules: {
'no-undef': 'off',
},
},
],
};
```

If you choose to leave on the ESLint `no-undef` lint rule, you can [manually define the set of allowed `globals` in your ESLint config](https://eslint.org/docs/user-guide/configuring/language-options#specifying-globals), and/or you can use one of the [pre-defined environment (`env`) configurations](https://eslint.org/docs/user-guide/configuring/language-options#specifying-environments).
Expand Down Expand Up @@ -206,7 +209,7 @@ Instead of using this plugin, we recommend using prettier's `--list-different` f
For example, our CI is setup to run the following command automatically, which blocks PRs that have not been formatted:

```bash npm2yarn
npm run prettier --list-different \"./**/*.{ts,js,json,md}\"
npm run prettier --list-different \"./**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}\"
```

### `eslint-plugin-import`
Expand Down
10 changes: 5 additions & 5 deletions package.json
Expand Up @@ -26,18 +26,18 @@
"check-clean-workspace-after-install": "git diff --quiet --exit-code",
"check-configs": "nx run-many --target=check-configs --all --parallel",
"check-docs": "nx run-many --target=check-docs --all --parallel",
"check-format": "prettier --list-different \"./**/*.{md,mdx,ts,js,tsx,jsx}\"",
"check-spelling": "cspell --config=.cspell.json \"**/*.{md,mdx,ts,js,tsx,jsx}\"",
"check-format": "prettier --list-different \"./**/*.{md,mdx,ts,mts,cts,js,cjs,mjs,tsx,jsx}\"",
"check-spelling": "cspell --config=.cspell.json \"**/*.{md,mdx,ts,mts,cts,js,cjs,mjs,tsx,jsx}\"",
"clean": "lerna clean && lerna run clean",
"cz": "git-cz",
"format": "prettier --write \"./**/*.{ts,tsx,js,jsx,json,md,css}\"",
"format": "prettier --write \"./**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}\"",
"generate-contributors": "yarn ts-node --transpile-only ./tools/generate-contributors.ts && yarn all-contributors generate",
"generate-sponsors": "yarn ts-node --transpile-only ./tools/generate-sponsors.ts",
"generate-website-dts": "yarn ts-node --transpile-only ./tools/generate-website-dts.ts",
"lint-fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
"lint-fix": "eslint . --fix",
"lint-markdown-fix": "yarn lint-markdown --fix",
"lint-markdown": "markdownlint \"**/*.md\" --config=.markdownlint.json --ignore-path=.markdownlintignore",
"lint": "cross-env NODE_OPTIONS=\"--max-old-space-size=16384\" eslint . --ext .js,.jsx,.ts,.tsx",
"lint": "cross-env NODE_OPTIONS=\"--max-old-space-size=16384\" eslint .",
"postinstall": "yarn husky install && yarn build",
"pre-commit": "yarn lint-staged",
"pre-push": "yarn check-format",
Expand Down
4 changes: 2 additions & 2 deletions packages/ast-spec/package.json
Expand Up @@ -33,8 +33,8 @@
"clean": "tsc -b tsconfig.build.json --clean",
"postclean": "rimraf dist && rimraf _ts3.4 && rimraf .rollup.cache && rimraf coverage",
"clean-fixtures": "rimraf -g \"./src/**/fixtures/**/snapshots\"",
"format": "prettier --write \"./**/*.{ts,js,json,md}\" --ignore-path ../../.prettierignore",
"lint": "eslint . --ext .js,.ts --ignore-path='../../.eslintignore'",
"format": "prettier --write \"./**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}\" --ignore-path ../../.prettierignore",
"lint": "eslint . --ignore-path='../../.eslintignore'",
"test": "jest",
"typecheck": "tsc -p tsconfig.json --noEmit"
},
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-plugin-internal/package.json
Expand Up @@ -7,8 +7,8 @@
"build": "tsc -b tsconfig.build.json",
"clean": "tsc -b tsconfig.build.json --clean",
"postclean": "rimraf dist && rimraf coverage",
"format": "prettier --write \"./**/*.{ts,js,json,md}\" --ignore-path ../../.prettierignore",
"lint": "eslint . --ext .js,.ts --ignore-path='../../.eslintignore'",
"format": "prettier --write \"./**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}\" --ignore-path ../../.prettierignore",
"lint": "eslint . --ignore-path='../../.eslintignore'",
"test": "jest --coverage",
"typecheck": "tsc -p tsconfig.json --noEmit"
},
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-plugin-tslint/package.json
Expand Up @@ -32,8 +32,8 @@
"build": "tsc -b tsconfig.build.json",
"clean": "tsc -b tsconfig.build.json --clean",
"postclean": "rimraf dist && rimraf coverage",
"format": "prettier --write \"./**/*.{ts,js,json,md}\" --ignore-path ../../.prettierignore",
"lint": "eslint . --ext .js,.ts --ignore-path='../../.eslintignore'",
"format": "prettier --write \"./**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}\" --ignore-path ../../.prettierignore",
"lint": "eslint . --ignore-path='../../.eslintignore'",
"test": "jest --coverage",
"typecheck": "tsc -p tsconfig.json --noEmit"
},
Expand Down
2 changes: 0 additions & 2 deletions packages/eslint-plugin/README.md
Expand Up @@ -59,8 +59,6 @@ You can also enable all the recommended rules for our plugin. Add `plugin:@types
}
```

**Note: Make sure to use `eslint --ext .js,.ts` since by [default](https://eslint.org/docs/user-guide/command-line-interface#--ext) `eslint` will only search for `.js` files.**

### Recommended Configs

You can also use [`eslint:recommended`](https://eslint.org/docs/rules/) (the set of rules which are recommended for all projects by the ESLint Team) with this plugin:
Expand Down
Expand Up @@ -95,7 +95,7 @@ const defaults = {

### Configuring in a mixed JS/TS codebase

If you are working on a codebase within which you lint non-TypeScript code (i.e. `.js`/`.jsx`), you should ensure that you should use [ESLint `overrides`](https://eslint.org/docs/user-guide/configuring#disabling-rules-only-for-a-group-of-files) to only enable the rule on `.ts`/`.tsx` files. If you don't, then you will get unfixable lint errors reported within `.js`/`.jsx` files.
If you are working on a codebase within which you lint non-TypeScript code (i.e. `.js`/`.mjs`/`.cjs`/`.jsx`), you should ensure that you should use [ESLint `overrides`](https://eslint.org/docs/user-guide/configuring#disabling-rules-only-for-a-group-of-files) to only enable the rule on `.ts`/`.mts`/`.cts`/`.tsx` files. If you don't, then you will get unfixable lint errors reported within `.js`/`.mjs`/`.cjs`/`.jsx` files.

```jsonc
{
Expand All @@ -106,7 +106,7 @@ If you are working on a codebase within which you lint non-TypeScript code (i.e.
"overrides": [
{
// enable the rule specifically for TypeScript files
"files": ["*.ts", "*.tsx"],
"files": ["*.ts", "*.mts", "*.cts", "*.tsx"],
"rules": {
"@typescript-eslint/explicit-function-return-type": ["error"]
}
Expand Down
Expand Up @@ -39,7 +39,7 @@ const defaultOptions: Options = {

### Configuring in a mixed JS/TS codebase

If you are working on a codebase within which you lint non-TypeScript code (i.e. `.js`/`.jsx`), you should ensure that you should use [ESLint `overrides`](https://eslint.org/docs/user-guide/configuring#disabling-rules-only-for-a-group-of-files) to only enable the rule on `.ts`/`.tsx` files. If you don't, then you will get unfixable lint errors reported within `.js`/`.jsx` files.
If you are working on a codebase within which you lint non-TypeScript code (i.e. `.js`/`.mjs`/`.cjs`/`.jsx`), you should ensure that you should use [ESLint `overrides`](https://eslint.org/docs/user-guide/configuring#disabling-rules-only-for-a-group-of-files) to only enable the rule on `.ts`/`.mts`/`.cts`/`.tsx` files. If you don't, then you will get unfixable lint errors reported within `.js`/`.mjs`/`.cjs`/`.jsx` files.

```jsonc
{
Expand All @@ -50,7 +50,7 @@ If you are working on a codebase within which you lint non-TypeScript code (i.e.
"overrides": [
{
// enable the rule specifically for TypeScript files
"files": ["*.ts", "*.tsx"],
"files": ["*.ts", "*.mts", "*.cts", "*.tsx"],
"rules": {
"@typescript-eslint/explicit-member-accessibility": ["error"]
}
Expand Down
Expand Up @@ -110,7 +110,7 @@ const defaults = {

### Configuring in a mixed JS/TS codebase

If you are working on a codebase within which you lint non-TypeScript code (i.e. `.js`/`.jsx`), you should ensure that you should use [ESLint `overrides`](https://eslint.org/docs/user-guide/configuring#disabling-rules-only-for-a-group-of-files) to only enable the rule on `.ts`/`.tsx` files. If you don't, then you will get unfixable lint errors reported within `.js`/`.jsx` files.
If you are working on a codebase within which you lint non-TypeScript code (i.e. `.js`/`.mjs`/`.cjs`/`.jsx`), you should ensure that you should use [ESLint `overrides`](https://eslint.org/docs/user-guide/configuring#disabling-rules-only-for-a-group-of-files) to only enable the rule on `.ts`/`.mts`/`.cts`/`.tsx` files. If you don't, then you will get unfixable lint errors reported within `.js`/`.mjs`/`.cjs`/`.jsx` files.

```jsonc
{
Expand All @@ -121,7 +121,7 @@ If you are working on a codebase within which you lint non-TypeScript code (i.e.
"overrides": [
{
// enable the rule specifically for TypeScript files
"files": ["*.ts", "*.tsx"],
"files": ["*.ts", "*.mts", "*.cts", "*.tsx"],
"rules": {
"@typescript-eslint/explicit-module-boundary-types": ["error"]
}
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-plugin/package.json
Expand Up @@ -36,10 +36,10 @@
"check-configs": "jest tests/configs.test.ts --runTestsByPath --silent --runInBand",
"clean": "tsc -b tsconfig.build.json --clean",
"postclean": "rimraf dist && rimraf coverage",
"format": "prettier --write \"./**/*.{ts,js,json,md}\" --ignore-path ../../.prettierignore",
"format": "prettier --write \"./**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}\" --ignore-path ../../.prettierignore",
"generate:configs": "../../node_modules/.bin/ts-node --files --transpile-only tools/generate-configs.ts",
"generate:rules-lists": "../../node_modules/.bin/ts-node --files --transpile-only tools/generate-rules-lists.ts",
"lint": "eslint . --ext .js,.ts --ignore-path ../../.eslintignore",
"lint": "eslint . --ignore-path ../../.eslintignore",
"test": "jest --coverage",
"typecheck": "tsc -p tsconfig.json --noEmit"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/src/configs/eslint-recommended.ts
Expand Up @@ -6,7 +6,7 @@
export = {
overrides: [
{
files: ['*.ts', '*.tsx'],
files: ['*.ts', '*.tsx', '*.mts', '*.cts'],
rules: {
'constructor-super': 'off', // ts(2335) & ts(2377)
'getter-return': 'off', // ts(2378)
Expand Down
14 changes: 13 additions & 1 deletion packages/eslint-plugin/src/util/misc.ts
Expand Up @@ -4,12 +4,24 @@

import { AST_NODE_TYPES, TSESLint, TSESTree } from '@typescript-eslint/utils';
import { requiresQuoting } from '@typescript-eslint/type-utils';
import * as ts from 'typescript';

const DEFINITION_EXTENSIONS = [
ts.Extension.Dts,
ts.Extension.Dcts,
ts.Extension.Dmts,
] as const;
/**
* Check if the context file name is *.d.ts or *.d.tsx
*/
function isDefinitionFile(fileName: string): boolean {
return /\.d\.tsx?$/i.test(fileName || '');
const lowerFileName = fileName.toLowerCase();
for (const definitionExt of DEFINITION_EXTENSIONS) {
if (lowerFileName.endsWith(definitionExt)) {
return true;
}
}
return false;
}

/**
Expand Down
17 changes: 12 additions & 5 deletions packages/eslint-plugin/tests/util.test.ts
@@ -1,7 +1,7 @@
import * as util from '../src/util';

describe('isDefinitionFile', () => {
it('returns false for non-definition files', () => {
describe('returns false for non-definition files', () => {
const invalid = [
'test.js',
'test.jsx',
Expand All @@ -15,18 +15,25 @@ describe('isDefinitionFile', () => {
'test.tsx',
'test.TS',
'test.TSX',
// yes, it's not a definition file if it's a `.d.tsx`!
'test.d.tsx',
'test.D.TSX',
];

invalid.forEach(f => {
expect(util.isDefinitionFile(f)).toBe(false);
it(f, () => {
expect(util.isDefinitionFile(f)).toBe(false);
});
});
});

it('returns true for definition files', () => {
const valid = ['test.d.ts', 'test.d.tsx', 'test.D.TS', 'test.D.TSX'];
describe('returns true for definition files', () => {
const valid = ['test.d.ts', 'test.D.TS'];

valid.forEach(f => {
expect(util.isDefinitionFile(f)).toBe(true);
it(f, () => {
expect(util.isDefinitionFile(f)).toBe(true);
});
});
});
});
Expand Down
4 changes: 2 additions & 2 deletions packages/experimental-utils/package.json
Expand Up @@ -33,8 +33,8 @@
"postbuild": "downlevel-dts dist _ts3.4/dist",
"clean": "tsc -b tsconfig.build.json --clean",
"postclean": "rimraf dist && rimraf _ts3.4 && rimraf coverage",
"format": "prettier --write \"./**/*.{ts,js,json,md}\" --ignore-path ../../.prettierignore",
"lint": "eslint . --ext .js,.ts --ignore-path='../../.eslintignore'",
"format": "prettier --write \"./**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}\" --ignore-path ../../.prettierignore",
"lint": "eslint . --ignore-path='../../.eslintignore'",
"typecheck": "tsc -p tsconfig.json --noEmit"
},
"dependencies": {
Expand Down
24 changes: 14 additions & 10 deletions packages/parser/README.md
Expand Up @@ -78,16 +78,19 @@ Default `false`.

Enable parsing JSX when `true`. More details can be found [here](https://www.typescriptlang.org/docs/handbook/jsx.html).

**NOTE:** this setting does not affect known file types (`.js`, `.jsx`, `.ts`, `.tsx`, `.json`) because the TypeScript compiler has its own internal handling for known file extensions. The exact behavior is as follows:
**NOTE:** this setting does not affect known file types (`.js`, `.mjs`, `.cjs`, `.jsx`, `.ts`, `.mts`, `.cts`, `.tsx`, `.json`) because the TypeScript compiler has its own internal handling for known file extensions.

- if `parserOptions.project` is _not_ provided:
- `.js`, `.jsx`, `.tsx` files are parsed as if this is true.
- `.ts` files are parsed as if this is false.
- unknown extensions (`.md`, `.vue`) will respect this setting.
- if `parserOptions.project` is provided (i.e. you are using rules with type information):
- `.js`, `.jsx`, `.tsx` files are parsed as if this is true.
- `.ts` files are parsed as if this is false.
- "unknown" extensions (`.md`, `.vue`) **are parsed as if this is false**.
<!-- https://github.com/microsoft/TypeScript/blob/d6e483b8dabd8fd37c00954c3f2184bb7f1eb90c/src/compiler/utilities.ts#L6281-L6285 -->

The exact behavior is as follows:

- `.js`, `.mjs`, `.cjs`, `.jsx`, `.tsx` files are always parsed as if this is `true`.
- `.ts`, `.mts`, `.cts` files are always parsed as if this is `false`.
- For "unknown" extensions (`.md`, `.vue`):
- If `parserOptions.project` is _not_ provided:
- The setting will be respected.
- If `parserOptions.project` is provided (i.e. you are using rules with type information):
- **always parsed as if this is `false`**

### `parserOptions.ecmaFeatures.globalReturn`

Expand Down Expand Up @@ -203,7 +206,8 @@ For example, by default it will ensure that a glob like `./**/tsconfig.json` wil
Default `undefined`.

This option allows you to provide one or more additional file extensions which should be considered in the TypeScript Program compilation.
The default extensions are `.ts`, `.tsx`, `.js`, and `.jsx`. Add extensions starting with `.`, followed by the file extension. E.g. for a `.vue` file use `"extraFileExtensions": [".vue"]`.
The default extensions are `['.js', '.mjs', '.cjs', '.jsx', '.ts', '.mts', '.cts', '.tsx']`.
Add extensions starting with `.`, followed by the file extension. E.g. for a `.vue` file use `"extraFileExtensions": [".vue"]`.

### `parserOptions.warnOnUnsupportedTypeScriptVersion`

Expand Down
4 changes: 2 additions & 2 deletions packages/parser/package.json
Expand Up @@ -35,8 +35,8 @@
"postbuild": "downlevel-dts dist _ts3.4/dist",
"clean": "tsc -b tsconfig.build.json --clean",
"postclean": "rimraf dist && rimraf _ts3.4 && rimraf coverage",
"format": "prettier --write \"./**/*.{ts,js,json,md}\" --ignore-path ../../.prettierignore",
"lint": "eslint . --ext .js,.ts --ignore-path='../../.eslintignore'",
"format": "prettier --write \"./**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}\" --ignore-path ../../.prettierignore",
"lint": "eslint . --ignore-path='../../.eslintignore'",
"test": "jest --coverage",
"typecheck": "tsc -p tsconfig.json --noEmit"
},
Expand Down
9 changes: 1 addition & 8 deletions packages/parser/src/parser.ts
Expand Up @@ -36,7 +36,7 @@ function validateBoolean(
return value;
}

const LIB_FILENAME_REGEX = /lib\.(.+)\.d\.ts$/;
const LIB_FILENAME_REGEX = /lib\.(.+)\.d\.[cm]?ts$/;
function getLib(compilerOptions: CompilerOptions): Lib[] {
if (compilerOptions.lib) {
return compilerOptions.lib.reduce((acc, lib) => {
Expand Down Expand Up @@ -110,13 +110,6 @@ function parseForESLint(
sourceType: options.sourceType,
};

if (typeof options.filePath === 'string') {
const tsx = options.filePath.endsWith('.tsx');
if (tsx || options.filePath.endsWith('.ts')) {
parserOptions.jsx = tsx;
}
}

/**
* Allow the user to suppress the warning from typescript-estree if they are using an unsupported
* version of TypeScript
Expand Down
2 changes: 1 addition & 1 deletion packages/scope-manager/package.json
Expand Up @@ -31,7 +31,7 @@
"build": "cd ../../ && nx build @typescript-eslint/scope-manager",
"clean": "cd ../../ && nx clean @typescript-eslint/scope-manager",
"clean-fixtures": "cd ../../ && nx clean-fixtures @typescript-eslint/scope-manager",
"format": "prettier --write \"./**/*.{ts,js,json,md}\" --ignore-path ../../.prettierignore",
"format": "prettier --write \"./**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}\" --ignore-path ../../.prettierignore",
"generate:lib": "cd ../../ && nx generate-lib @typescript-eslint/scope-manager",
"lint": "cd ../../ && nx lint @typescript-eslint/scope-manager",
"test": "cd ../../ && nx test @typescript-eslint/scope-manager --code-coverage",
Expand Down

0 comments on commit efc147b

Please sign in to comment.