Skip to content

feat(typescript-estree): stabilize EXPERIMENTAL_useProjectService as projectService #9084

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

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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"Airbnb",
"Airbnb's",
"ambiently",
"allowdefaultprojectforfiles",
"allowdefaultproject",
"Armano",
"astexplorer",
"Astro",
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -240,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 @@ -265,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
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
## 7.10.0 (2024-05-20)


### 🚀 Features

- **eslint-plugin:** [sort-type-constituents] support case sensitive sorting ([#8760](https://github.com/typescript-eslint/typescript-eslint/pull/8760))

### 🩹 Fixes

- **eslint-plugin:** [prefer-regexp-exec] fix heuristic to check whether regex may contain global flag ([#8764](https://github.com/typescript-eslint/typescript-eslint/pull/8764))
- **typescript-estree:** don't add in-project files to defaultProjectMatchedFiles ([#9097](https://github.com/typescript-eslint/typescript-eslint/pull/9097))
- **utils:** remove function form type from flat config `files` and `ignores` ([#9111](https://github.com/typescript-eslint/typescript-eslint/pull/9111))

### ❤️ Thank You

- auvred @auvred
- Emanuel Hoogeveen @ehoogeveen-medweb
- jsfm01 @jsfm01
- Kirk Waiblinger

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

## 7.9.0 (2024-05-13)


Expand Down
100 changes: 68 additions & 32 deletions docs/packages/Parser.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ interface ParserOptions {
programs?: import('typescript').Program[];
project?: string | string[] | boolean | null;
projectFolderIgnoreList?: string[];
projectService?: boolean | ProjectServiceOptions;
tsconfigRootDir?: string;
warnOnUnsupportedTypeScriptVersion?: boolean;
EXPERIMENTAL_useProjectService?: boolean;
}
```

Expand Down Expand Up @@ -205,9 +205,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 @@ -261,7 +265,68 @@ 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).
For an option that allows linting files outside of your TSConfig file(s), see [`projectService`](#projectService).

<HiddenHeading id="experimental_useprojectservice" />

### `projectService`

> Default `false`.

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`).

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

**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

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 )

#### `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`

Expand Down Expand Up @@ -303,35 +368,6 @@ Please only submit bug reports when using the officially supported version.
=============
```

### `EXPERIMENTAL_useProjectService`

> 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.
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`).

```js
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
EXPERIMENTAL_useProjectService: true,
},
};
```

This option should bring two main benefits:

- 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.

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.

## Utilities

### `createProgram(configFile, projectDirectory)`
Expand Down
20 changes: 9 additions & 11 deletions docs/packages/TypeScript_ESTree.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -198,15 +198,6 @@ interface ParseAndGenerateServicesOptions extends ParseOptions {
*/
errorOnTypeScriptSyntacticAndSemanticIssues?: boolean;

/**
* ***EXPERIMENTAL FLAG*** - Use this at your own risk.
*
* Whether to create a shared TypeScript server to power program creation.
*
* @see https://github.com/typescript-eslint/typescript-eslint/issues/6575
*/
EXPERIMENTAL_useProjectService?: boolean | ProjectServiceOptions;

/**
* ***EXPERIMENTAL FLAG*** - Use this at your own risk.
*
Expand Down Expand Up @@ -249,6 +240,8 @@ interface ParseAndGenerateServicesOptions extends ParseOptions {
* If this is provided, type information will be returned.
*
* If set to `false`, `null`, or `undefined`, type information will not be returned.
*
* Note that {@link projectService} is now preferred.
*/
project?: string[] | string | boolean | null;

Expand All @@ -261,6 +254,11 @@ interface ParseAndGenerateServicesOptions extends ParseOptions {
*/
projectFolderIgnoreList?: string[];

/**
* Whether to create a shared TypeScript project service to power program creation.
*/
projectService?: boolean | ProjectServiceOptions;

/**
* The absolute path to the root directory for all provided `project`s.
*/
Expand All @@ -281,15 +279,15 @@ interface ProjectServiceOptions {
/**
* Globs of files to allow running with the default project compiler options.
*/
allowDefaultProjectForFiles?: string[];
allowDefaultProject?: string[];

/**
* Path to a TSConfig to use instead of TypeScript's default project configuration.
*/
defaultProject?: string;

/**
* The maximum number of files {@link allowDefaultProjectForFiles} may match.
* The maximum number of files {@link 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!
Expand Down
14 changes: 7 additions & 7 deletions docs/troubleshooting/FAQ.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,20 @@ If you don't find an existing extension rule, or the extension rule doesn't work
> We release a new version our tooling every week.
> _Please_ ensure that you [check our the latest list of "extension" rules](/rules/#extension-rules) **_before_** filing an issue.

<HiddenHeading id="allowdefaultprojectforfiles-glob-too-wide" />
<HiddenHeading id="allowDefaultProject-glob-too-wide" />

## I get errors telling me "Having many files run with the default project is known to cause performance issues and slow down linting."

These errors are caused by using the [`EXPERIMENTAL_useProjectService`](../packages/Parser.mdx#experimental_useprojectservice) `allowDefaultProjectForFiles` with an excessively wide glob.
`allowDefaultProjectForFiles` causes a new TypeScript "program" to be built for each "out of project" file it includes, which incurs a performance overhead for each file.
These errors are caused by using the [`projectService`](../packages/Parser.mdx#projectService) `allowDefaultProject` with an excessively wide glob.
`allowDefaultProject` causes a new TypeScript "program" to be built for each "out of project" file it includes, which incurs a performance overhead for each file.

To resolve this error, narrow the glob(s) used for `allowDefaultProjectForFiles` to include fewer files.
To resolve this error, narrow the glob(s) used for `allowDefaultProject` to include fewer files.
For example:

```diff title="eslint.config.js"
parserOptions: {
EXPERIMENTAL_useProjectService: {
allowDefaultProjectForFiles: [
projectService: {
allowDefaultProject: [
- "**/*.js",
+ "./*.js"
]
Expand Down Expand Up @@ -533,6 +533,6 @@ If you think you're having issues with performance, see our [Performance Trouble

## Are TypeScript project references supported?

Yes, but only with [`EXPERIMENTAL_useProjectService`](../packages/Parser.mdx#experimental_useprojectservice).
Yes, but only with [`projectService`](../packages/Parser.mdx#projectService).

See [issue #2094 discussing project references](https://github.com/typescript-eslint/typescript-eslint/issues/2094) for more details.
6 changes: 6 additions & 0 deletions packages/ast-spec/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 7.10.0 (2024-05-20)

This was a version bump only for ast-spec to align it with other projects, there were no code changes.

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

## 7.9.0 (2024-05-13)

This was a version bump only for ast-spec to align it with other projects, there were no code changes.
Expand Down
2 changes: 1 addition & 1 deletion packages/ast-spec/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@typescript-eslint/ast-spec",
"version": "7.9.0",
"version": "7.10.0",
"description": "Complete specification for the TypeScript-ESTree AST",
"private": true,
"keywords": [
Expand Down
6 changes: 6 additions & 0 deletions packages/eslint-plugin-internal/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 7.10.0 (2024-05-20)

This was a version bump only for eslint-plugin-internal to align it with other projects, there were no code changes.

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

## 7.9.0 (2024-05-13)

This was a version bump only for eslint-plugin-internal to align it with other projects, there were no code changes.
Expand Down
10 changes: 5 additions & 5 deletions packages/eslint-plugin-internal/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@typescript-eslint/eslint-plugin-internal",
"version": "7.9.0",
"version": "7.10.0",
"private": true,
"main": "dist/index.js",
"types": "index.d.ts",
Expand All @@ -15,10 +15,10 @@
},
"dependencies": {
"@prettier/sync": "^0.5.1",
"@typescript-eslint/rule-tester": "7.9.0",
"@typescript-eslint/scope-manager": "7.9.0",
"@typescript-eslint/type-utils": "7.9.0",
"@typescript-eslint/utils": "7.9.0",
"@typescript-eslint/rule-tester": "7.10.0",
"@typescript-eslint/scope-manager": "7.10.0",
"@typescript-eslint/type-utils": "7.10.0",
"@typescript-eslint/utils": "7.10.0",
"prettier": "^3.2.5"
},
"devDependencies": {
Expand Down
22 changes: 22 additions & 0 deletions packages/eslint-plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
## 7.10.0 (2024-05-20)


### 🚀 Features

- **eslint-plugin:** [sort-type-constituents] support case sensitive sorting


### 🩹 Fixes

- **eslint-plugin:** [prefer-regexp-exec] fix heuristic to check whether regex may contain global flag


### ❤️ Thank You

- auvred
- Emanuel Hoogeveen
- jsfm01
- Kirk Waiblinger

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

## 7.9.0 (2024-05-13)


Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/docs/rules/no-floating-promises.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ With this option set to `true`, and if you are using `no-void`, you should turn

### `ignoreIIFE`

This allows you to skip checking of async IIFEs (Immediately Invoked function Expressions).
This allows you to skip checking of async IIFEs (Immediately Invoked Function Expressions).

Examples of **correct** code for this rule with `{ ignoreIIFE: true }`:

Expand Down
14 changes: 7 additions & 7 deletions packages/eslint-plugin/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@typescript-eslint/eslint-plugin",
"version": "7.9.0",
"version": "7.10.0",
"description": "TypeScript plugin for ESLint",
"files": [
"dist",
Expand Down Expand Up @@ -62,10 +62,10 @@
},
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "7.9.0",
"@typescript-eslint/type-utils": "7.9.0",
"@typescript-eslint/utils": "7.9.0",
"@typescript-eslint/visitor-keys": "7.9.0",
"@typescript-eslint/scope-manager": "7.10.0",
"@typescript-eslint/type-utils": "7.10.0",
"@typescript-eslint/utils": "7.10.0",
"@typescript-eslint/visitor-keys": "7.10.0",
"graphemer": "^1.4.0",
"ignore": "^5.3.1",
"natural-compare": "^1.4.0",
Expand All @@ -76,8 +76,8 @@
"@types/marked": "^5.0.2",
"@types/mdast": "^4.0.3",
"@types/natural-compare": "*",
"@typescript-eslint/rule-schema-to-typescript-types": "7.9.0",
"@typescript-eslint/rule-tester": "7.9.0",
"@typescript-eslint/rule-schema-to-typescript-types": "7.10.0",
"@typescript-eslint/rule-tester": "7.10.0",
"ajv": "^6.12.6",
"cross-env": "^7.0.3",
"cross-fetch": "*",
Expand Down
Loading
Loading