Skip to content

fix(typescript-estree): adds project service watch to add new files to project #9353

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

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
6464df2
feat(typescript-estree): remove slow deprecated and isolated programs…
JoshuaKGoldberg Apr 15, 2024
b8e8853
fix(typescript-estree): add TSEnumBody node for TSEnumDeclaration bod…
JoshuaKGoldberg Apr 15, 2024
2d835ee
fix(typescript-estree): enable dot globs for project by default (#8818)
JoshuaKGoldberg Apr 19, 2024
1a22a53
feat(typescript-estree): split TSMappedType typeParameter into constr…
JoshuaKGoldberg Apr 19, 2024
adf8f3b
feat(eslint-plugin): remove formatting/layout rules (#8833)
JoshuaKGoldberg Apr 19, 2024
151cae2
feat(eslint-plugin): [prefer-nullish-coalescing] change ignoreConditi…
JoshuaKGoldberg Apr 22, 2024
61c2ee7
feat(eslint-plugin): deprecate no-loss-of-precision extension rule (#…
JoshuaKGoldberg Apr 22, 2024
f9520fe
Merge branch 'main' into v8
JoshuaKGoldberg Apr 22, 2024
bea2e44
chore(type-utils): remove getTypeArguments (#8938)
y-hsgw Apr 22, 2024
f4cbbe6
chore(type-utils)!: remove IsNullableTypeOptions interface (#8934)
thuchede Apr 23, 2024
8284a18
Merge branch 'main' into v8
JoshuaKGoldberg Apr 25, 2024
21abb00
Merge branch 'main' into v8
JoshuaKGoldberg Apr 26, 2024
67fbca5
feat(eslint-plugin): [no-unused-vars] align catch behavior to ESLint …
JoshuaKGoldberg Apr 26, 2024
3cdb011
chore: bump minimum versions for v8 (#8973)
JoshuaKGoldberg Apr 26, 2024
7bdd008
Merge branch 'main' into v8
JoshuaKGoldberg Apr 26, 2024
6028711
feat(utils): add Linter configType constructor option (#8999)
JoshuaKGoldberg Apr 26, 2024
5650142
feat(typescript-estree): rename automaticSingleRunInference to disall…
JoshuaKGoldberg Apr 26, 2024
571bb9d
feat(parser): always enable comment, loc, range, tokens (#8617)
JoshuaKGoldberg Apr 26, 2024
e21b26e
feat(utils): swap LegacyESLint out for FlatESLint as ESLint export (#…
JoshuaKGoldberg Apr 26, 2024
47d874d
test(rule-tester): update test config snapshots to include new disall…
auvred Apr 28, 2024
25a126b
Merge branch 'main' into v8
JoshuaKGoldberg Apr 29, 2024
1b36f83
chore: fix v8 branch snapshots for flat-config-types (#9029)
JoshuaKGoldberg Apr 29, 2024
496dd36
Merge branch 'main' into v8
JoshuaKGoldberg Apr 29, 2024
72d1066
docs: remove eslint v9 tracking issue from main readme for v8 (#9006)
kirkwaiblinger Apr 29, 2024
07044c6
feat(utils): remove deprecated context helpers (#9000)
abrahamguo Apr 30, 2024
b1c92d4
feat(utils): allow specifying additional rule meta.docs in RuleCreato…
JoshuaKGoldberg May 9, 2024
04f1938
Merge branch 'main'
JoshuaKGoldberg May 9, 2024
fd097ef
feat(eslint-plugin): split no-empty-object-type out from ban-types an…
JoshuaKGoldberg May 12, 2024
b765f7b
feat: support ESLint v9 (#9002)
JoshuaKGoldberg May 12, 2024
0d85360
Merge branch 'main' into v8
JoshuaKGoldberg May 12, 2024
94bd289
fix: correct eslint-plugin's peerDependency on parser@8 (#9089)
JoshuaKGoldberg May 13, 2024
5753fe5
fix(eslint-plugin): include alpha pre-releases in parser peer depende…
bachmacintosh May 15, 2024
5c80828
feat(rule-tester): support multipass fixes (#8883)
auvred May 16, 2024
87a0a48
Merge branch 'main'
JoshuaKGoldberg May 18, 2024
ad3ff43
feat(ast-spec): remove deprecated type params (#8933)
abrahamguo May 24, 2024
b9796c1
feat(typescript-estree): stabilize EXPERIMENTAL_useProjectService as …
JoshuaKGoldberg May 24, 2024
c0bf6fc
Merge branch 'main'
JoshuaKGoldberg May 26, 2024
e8e79e0
feat(eslint-plugin): remove deprecated no-throw-literal rule (#9092)
y-hsgw May 26, 2024
92d4a26
feat(typescript-estree): remove EXPERIMENTAL_useSourceOfProjectRefere…
JoshuaKGoldberg May 27, 2024
ae1414c
feat(eslint-plugin): apply initial config changes for v8 (#9079)
JoshuaKGoldberg May 27, 2024
d97366e
chore(eslint-plugin): deprecate no-var-requires in favor of no-requir…
arkapratimc May 28, 2024
4f0a46f
chore: use recommended config for Node.js 18 in TSConfig (#9113)
lesha1201 May 28, 2024
540d97e
chore: enable `prefer-object-has-own` ESLint rule (#9123)
lesha1201 May 28, 2024
c3031c8
Merge branch 'main'
JoshuaKGoldberg May 28, 2024
06b0e08
Two introduced lint suppressions
JoshuaKGoldberg May 28, 2024
713fc21
Update RuleTester.test.ts snapshots
JoshuaKGoldberg May 29, 2024
8897c14
fix(typescript-estree): pass extraFileExtensions to projectService (#…
alfredringstad May 29, 2024
04591f0
Merge branch 'main' into v8
JoshuaKGoldberg May 29, 2024
6966e3b
Fix eslint-plugin-internal tests, or maybe just made them worse...
JoshuaKGoldberg May 29, 2024
10aecc8
Fix a parse.test.ts spacing issue
JoshuaKGoldberg May 29, 2024
a42afd3
One more EXPERIMENTAL_ rename
JoshuaKGoldberg May 29, 2024
8d4bba9
fix snapshot ordering
JoshuaKGoldberg May 29, 2024
e3eb1ad
fix(rule-tester): set configType to eslintrc in Linter options (#9178)
JamesHenry May 30, 2024
f279b6d
docs: fix only-throw-error link to no-throw-literal
JoshuaKGoldberg May 30, 2024
7afd3f3
fix(rule-tester): re-apply updates from main (#9180)
JoshuaKGoldberg May 30, 2024
ebad5e4
Merge branch 'main'
JoshuaKGoldberg Jun 2, 2024
31e70cf
chore: fix introduced Object.hasOwn lint complaint
JoshuaKGoldberg Jun 2, 2024
b4fbf6d
Merge branch 'main' into v8
JoshuaKGoldberg Jun 3, 2024
7b6b8bc
feat(eslint-plugin): remove no-useless-template-literals (#9207)
y-hsgw Jun 4, 2024
b222625
Merge branch 'main'
JoshuaKGoldberg Jun 6, 2024
585423d
chore: fix test typing too
JoshuaKGoldberg Jun 6, 2024
8e95924
feat(eslint-plugin): [no-floating-promises] add 'allowForKnownSafeCal…
JoshuaKGoldberg Jun 8, 2024
3c3370f
feat(typescript-estree): also remove projectService in withoutProject…
JoshuaKGoldberg Jun 8, 2024
0f1b064
fix(types): allow ProjectServiceOptions for projectService (#9318)
JoshuaKGoldberg Jun 10, 2024
007850d
Merge branch 'main'
JoshuaKGoldberg Jun 12, 2024
5cd80ca
feat(eslint-plugin): replace ban-types with no-restricted-types, no-u…
JoshuaKGoldberg Jun 13, 2024
0151bc4
chore(typescript-estree): starting rework of Trie watcher
higherorderfunctor Jun 14, 2024
d294362
chore(typescript-estree): copy in mvp for feature
higherorderfunctor Jun 14, 2024
d3c3b25
chore(typescript-estree): updates to mvp
higherorderfunctor Jun 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 2 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
"words": [
"Airbnb",
"Airbnb's",
"allowdefaultprojectforfiles",
"ambiently",
"allowdefaultproject",
"ambiently",
"Armano",
"astexplorer",
Expand Down
27 changes: 23 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,25 @@ jobs:
run: yarn stylelint
working-directory: packages/website

eslint_v9_tests:
name: Run tests on ESLint v9
needs: [build]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install
uses: ./.github/actions/prepare-install
with:
node-version: ${{ env.PRIMARY_NODE_VERSION }}
- name: Build
uses: ./.github/actions/prepare-build
- run: yarn add eslint@9
- name: Run tests
run: yarn test
env:
CI: true

integration_tests:
name: Run integration tests on primary Node.js version
needs: [build]
Expand All @@ -148,7 +167,7 @@ jobs:
- name: Build
uses: ./.github/actions/prepare-build

- name: Run integrations tests
- name: Run integration tests
run: yarn test-integration
env:
CI: true
Expand Down Expand Up @@ -221,8 +240,8 @@ jobs:
# Sadly 1 day is the minimum
retention-days: 1

unit_tests_tsserver:
name: Run Unit Tests with Experimental TSServer
unit_tests_project_service:
name: Run Unit Tests with Project Service
needs: [build]
runs-on: ubuntu-latest
strategy:
Expand All @@ -246,7 +265,7 @@ jobs:
run: npx nx test ${{ matrix.package }} --coverage=false
env:
CI: true
TYPESCRIPT_ESLINT_EXPERIMENTAL_TSSERVER: true
TYPESCRIPT_ESLINT_PROJECT_SERVICE: true

upload_coverage:
name: Upload Codecov Coverage
Expand Down
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@
<p align="center">
👆
</p>
<p align="center">
Using ESLint v9? See: <a href="https://github.com/typescript-eslint/typescript-eslint/issues/8211">ESLint v9 Support</a>.
</p>
<!-- markdownlint-enable MD033 -->

## Code Contributors
Expand Down
26 changes: 26 additions & 0 deletions docs/developers/Custom_Rules.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,32 @@ export const rule = createRule<Options, MessageIds>({
});
```

#### Extra Rule Docs Types

By default, rule `meta.docs` is allowed to contain only `description` and `url` as described in [ESLint's Custom Rules > Rule Structure docs](https://eslint.org/docs/latest/extend/custom-rules#rule-structure).
Additional docs properties may be added as a type argument to `ESLintUtils.RuleCreator`:

```ts
interface MyPluginDocs {
recommended: boolean;
}

const createRule = ESLintUtils.RuleCreator<MyPluginDocs>(
name => `https://example.com/rule/${name}`,
);

createRule({
// ...
meta: {
docs: {
description: '...',
recommended: true,
},
// ...
},
});
```

### Undocumented Rules

Although it is generally not recommended to create custom rules without documentation, if you are sure you want to do this you can use the `ESLintUtils.RuleCreator.withoutDocs` function to directly create a rule.
Expand Down
2 changes: 1 addition & 1 deletion docs/maintenance/Issues.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ For enhancements meant to limit which kinds of nodes the rule targets, mark the
#### 🚀 New Rules

We're generally accepting of new rules that meet the above feature request criteria.
The biggest exception is rules that can roughly be implemented with [`@typescript-eslint/ban-types`](/rules/ban-types) and/or [`no-restricted-syntax`](https://eslint.org/docs/latest/rules/no-restricted-syntax).
The biggest exception is rules that can roughly be implemented with [`@typescript-eslint/no-restricted-types`](/rules/no-restricted-types) and/or [`no-restricted-syntax`](https://eslint.org/docs/latest/rules/no-restricted-syntax).

## Pruning Old Issues

Expand Down
159 changes: 98 additions & 61 deletions docs/packages/Parser.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ The following additional configuration options are available by specifying them

```ts
interface ParserOptions {
allowAutomaticSingleRunInference?: boolean;
cacheLifetime?: {
glob?: number | 'Infinity';
};
disallowAutomaticSingleRunInference?: boolean;
ecmaFeatures?: {
jsx?: boolean;
globalReturn?: boolean;
Expand All @@ -54,28 +54,29 @@ interface ParserOptions {
programs?: import('typescript').Program[];
project?: string | string[] | boolean | null;
projectFolderIgnoreList?: string[];
projectService?: boolean | ProjectServiceOptions;
tsconfigRootDir?: string;
warnOnUnsupportedTypeScriptVersion?: boolean;
EXPERIMENTAL_useProjectService?: boolean;
}
```

### `allowAutomaticSingleRunInference`
### `disallowAutomaticSingleRunInference`

> Default `process.env.TSESTREE_SINGLE_RUN` or `false`.
> Default `process.env.TSESTREE_SINGLE_RUN` or `true`.

Whether to use common heuristics to infer whether ESLint is being used as part of a single run (as opposed to `--fix` mode or in a persistent session such as an editor extension).
Whether to stop using common heuristics to infer whether ESLint is being used as part of a single run (as opposed to `--fix` mode or in a persistent session such as an editor extension).
In other words, typescript-eslint is faster by default, and this option disables an automatic performance optimization.

When typescript-eslint handles TypeScript Program management behind the scenes for [linting with type information](../getting-started/Typed_Linting.mdx), this distinction is important for performance.
There is significant overhead to managing TypeScript "Watch" Programs needed for the long-running use-case.
Being able to assume the single run case allows typescript-eslint to faster immutable Programs instead.

This setting's default value can be specified by setting a `TSESTREE_SINGLE_RUN` environment variable to `"false"` or `"true"`.
For example, `TSESTREE_SINGLE_RUN=true npx eslint .` will enable it.
For example, `TSESTREE_SINGLE_RUN=false npx eslint .` will disable it.

:::tip
We've seen `allowAutomaticSingleRunInference` improve linting speed in CI by up to 10-20%.
Our plan is to [enable `allowAutomaticSingleRunInference` by default in an upcoming major version](https://github.com/typescript-eslint/typescript-eslint/issues/8121).
:::note
We recommend leaving this option off if possible.
We've seen allowing automatic single run inference improve linting speed in CI by up to 10-20%.
:::

### `cacheLifetime`
Expand All @@ -84,7 +85,7 @@ This option allows you to granularly control our internal cache expiry lengths.

You can specify the number of seconds as an integer number, or the string 'Infinity' if you never want the cache to expire.

By default cache entries will be evicted after 30 seconds, or will persist indefinitely if the parser infers that it is a single run (see [`allowAutomaticSingleRunInference`](#allowAutomaticSingleRunInference)).
By default cache entries will be evicted after 30 seconds, or will persist indefinitely if the parser infers that it is a single run (see [`disallowAutomaticSingleRunInference`](#disallowAutomaticSingleRunInference)).

### `ecmaFeatures`

Expand Down Expand Up @@ -209,9 +210,13 @@ All linted files must be part of the provided program(s).

### `project`

:::note
We now recommend using [`projectService`](#projectservice) instead of `project` for easier configuration and faster linting.
:::

> Default `undefined`.

A path to your project's TSConfig. **This setting is required to use [rules which require type information](../getting-started/Typed_Linting.mdx)**.
A path to your project's TSConfig. **This setting or [`projectService`](#projectservice) are required to use [rules which require type information](../getting-started/Typed_Linting.mdx)**.

Accepted value types:

Expand Down Expand Up @@ -265,54 +270,15 @@ If this setting is specified, you must only lint files that are included in the
}
```

For an option that allows linting files outside of your TSConfig file(s), see [`EXPERIMENTAL_useProjectService`](#experimental_useprojectservice).

### `projectFolderIgnoreList`

> Default `["**/node_modules/**"]`.

This option allows you to ignore folders from being included in your provided list of `project`s.
This is useful if you have configured glob patterns, but want to make sure you ignore certain folders.

It accepts an array of globs to exclude from the `project` globs.

For example, by default it will ensure that a glob like `./**/tsconfig.json` will not match any `tsconfig`s within your `node_modules` folder (some npm packages do not exclude their source files from their published packages).

### `tsconfigRootDir`

> Default `undefined`.

This option allows you to provide the root directory for relative TSConfig paths specified in the `project` option above.
Doing so ensures running ESLint from a directory other than the root will still be able to find your TSConfig.

### `warnOnUnsupportedTypeScriptVersion`

> Default `true`.

This option allows you to toggle the warning that the parser will give you if you use a version of TypeScript which is not explicitly supported. The warning message would look like this:

```plaintext
=============

WARNING: You are currently running a version of TypeScript which is not officially supported by @typescript-eslint/typescript-estree.

You may find that it works just fine, or you may not.

SUPPORTED TYPESCRIPT VERSIONS: >=3.3.1 <5.1.0

YOUR TYPESCRIPT VERSION: 5.1.3
For an option that allows linting files outside of your TSConfig file(s), see [`projectService`](#projectService).

Please only submit bug reports when using the officially supported version.
<HiddenHeading id="experimental_useprojectservice" />

=============
```

### `EXPERIMENTAL_useProjectService`
### `projectService`

> Default `false`.

An experimental alternative to `parserOptions.project`.
This directs the parser to use a more seamless TypeScript API to generate type information for rules.
Specifies using TypeScript APIs to generate type information for rules.
It will automatically detect the TSConfig for each file (like `project: true`), and will also allow type information to be computed for JavaScript files without the `allowJs` compiler option (unlike `project: true`).

<Tabs groupId="eslint-config">
Expand All @@ -323,7 +289,7 @@ export default [
{
languageOptions: {
parserOptions: {
EXPERIMENTAL_useProjectService: true,
projectService: true,
},
},
},
Expand All @@ -337,25 +303,96 @@ export default [
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
EXPERIMENTAL_useProjectService: true,
projectService: true,
},
};
```

</TabItem>
</Tabs>

This option should bring two main benefits:
**This setting or [`project`](#project) are required to use [rules which require type information](../getting-started/Typed_Linting.mdx)**.

This option brings two main benefits over the older `project`:

- Simpler configurations: most projects shouldn't need to explicitly configure `project` paths or create `tsconfig.eslint.json`s
- Improved performance: this API is optimized on the TypeScript side for speed
- Initial versions of this option demonstrated performance changes in subsets of the typescript-eslint monorepo ranging from 11% slower to 70% faster

We're hopeful this option will eventually become the standard way to enable typed linting.
It switches the parser from manually creating TypeScript programs to instead calling the same "project services" API used by editors such as VS Code.
However, because it's so new and untested, we're keeping it under the `EXPERIMENTAL_` prefix for at least all of the `6.X` versions.
For more information, see:

- [feat(typescript-estree): add EXPERIMENTAL_useProjectService option to use TypeScript project service](https://github.com/typescript-eslint/typescript-eslint/pull/6754)
- [docs: blog post on parserOptions.projectService](docs: blog post on parserOptions.projectService )

See [feat(typescript-estree): add EXPERIMENTAL_useProjectService option to use TypeScript project service](https://github.com/typescript-eslint/typescript-eslint/pull/6754) for more information.
#### `ProjectServiceOptions`

The behavior of `parserOptions.projectService` can be customized by setting it to an object.

```js
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
projectService: {
allowDefaultProject: ['./*.js'],
},
},
};
```

##### `allowDefaultProject`

Globs of files to allow running with the default project compiler options despite not being matched by the project service.

##### `defaultProject`

Path to a TSConfig to use instead of TypeScript's default project configuration.

##### `maximumDefaultProjectFileMatchCount_THIS_WILL_SLOW_DOWN_LINTING`

> Default: `8`.

The maximum number of files [`allowDefaultProject`](#allowdefaultproject) may match.
Each file match slows down linting, so if you do need to use this, please file an informative issue on typescript-eslint explaining why - so we can help you avoid using it!

### `projectFolderIgnoreList`

> Default `["**/node_modules/**"]`.

This option allows you to ignore folders from being included in your provided list of `project`s.
This is useful if you have configured glob patterns, but want to make sure you ignore certain folders.

It accepts an array of globs to exclude from the `project` globs.

For example, by default it will ensure that a glob like `./**/tsconfig.json` will not match any `tsconfig`s within your `node_modules` folder (some npm packages do not exclude their source files from their published packages).

### `tsconfigRootDir`

> Default `undefined`.

This option allows you to provide the root directory for relative TSConfig paths specified in the `project` option above.
Doing so ensures running ESLint from a directory other than the root will still be able to find your TSConfig.

### `warnOnUnsupportedTypeScriptVersion`

> Default `true`.

This option allows you to toggle the warning that the parser will give you if you use a version of TypeScript which is not explicitly supported. The warning message would look like this:

```plaintext
=============

WARNING: You are currently running a version of TypeScript which is not officially supported by @typescript-eslint/typescript-estree.

You may find that it works just fine, or you may not.

SUPPORTED TYPESCRIPT VERSIONS: >=3.3.1 <5.1.0

YOUR TYPESCRIPT VERSION: 5.1.3

Please only submit bug reports when using the officially supported version.

=============
```

## Utilities

Expand Down
9 changes: 9 additions & 0 deletions docs/packages/Rule_Tester.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ ruleTester.run('my-rule', rule, {
/* ... */
],
},
// Multi-pass fixes can be tested using the array form of output.
// Note: this is unique to typescript-eslint, and doesn't exist in ESLint core.
{
code: 'const d = 1;',
output: ['const e = 1;', 'const f = 1;'],
errors: [
/* ... */
],
},

// suggestions can be tested via errors
{
Expand Down
Loading