Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat(typescript-estree): allow specifying project: true#6084

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 ourterms of service andprivacy 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 fromall commits
Commits
Show all changes
23 commits
Select commitHold shift + click to select a range
efec873
feat(typescript-estree): allow specifying project: true
JoshuaKGoldbergNov 25, 2022
4927c39
Also fix unchanged file for lint I guess
JoshuaKGoldbergNov 25, 2022
d01f2bf
Added docs
JoshuaKGoldbergNov 25, 2022
4bf121e
More tsconfigRootDir: __dirname removal
JoshuaKGoldbergNov 25, 2022
db656f5
Added some unit tests
JoshuaKGoldbergNov 25, 2022
003d993
you don't say
JoshuaKGoldbergNov 25, 2022
eb34a95
Undo createWatchProgram.ts
JoshuaKGoldbergNov 25, 2022
3a428c1
Merge branch 'main' into parser-options-project-true
JoshuaKGoldbergNov 28, 2022
9ae3ce6
Added parse tests
JoshuaKGoldbergNov 30, 2022
7cf6b80
Merge branch 'main' into parser-options-project-true
JoshuaKGoldbergNov 30, 2022
3682aaf
Merge branch 'main'
JoshuaKGoldbergDec 3, 2022
b024ad2
Fixed monorepos link
JoshuaKGoldbergDec 3, 2022
6b16b04
Cache under all directories
JoshuaKGoldbergDec 8, 2022
264a279
Added another test, just to be sure
JoshuaKGoldbergDec 8, 2022
725603e
Merge branch 'main' into parser-options-project-true
JoshuaKGoldbergDec 8, 2022
3c4850b
lint fix
JoshuaKGoldbergDec 10, 2022
16e52d5
Add back tsconfigRootDir
JoshuaKGoldbergDec 13, 2022
2be55de
Apply suggestions from code review
JoshuaKGoldbergJan 23, 2023
fb6465c
Back to string |
JoshuaKGoldbergJan 25, 2023
e6df49a
Merge branch main and use ExpiringCache and idk what else git is hard
JoshuaKGoldbergFeb 4, 2023
edc11e5
Fix website build
JoshuaKGoldbergFeb 4, 2023
315bcde
Fix the build
JoshuaKGoldbergFeb 4, 2023
040a56a
A global tsconfigMatchCache, with a test
JoshuaKGoldbergFeb 9, 2023
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
9 changes: 8 additions & 1 deletiondocs/architecture/Parser.mdx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -45,7 +45,7 @@ interface ParserOptions {
lib?: string[];
moduleResolver?: string;
program?: import('typescript').Program;
project?: string | string[];
project?: string | string[] | true;
projectFolderIgnoreList?: string[];
tsconfigRootDir?: string;
warnOnUnsupportedTypeScriptVersion?: boolean;
Expand DownExpand Up@@ -188,6 +188,9 @@ This option allows you to provide a path to your project's `tsconfig.json`. **Th
- Accepted values:

```js
// find the tsconfig.json nearest each source file
project: true,

// path
project: './tsconfig.json';

Expand All@@ -198,6 +201,10 @@ This option allows you to provide a path to your project's `tsconfig.json`. **Th
project: ['./packages/**/tsconfig.json', './separate-package/tsconfig.json'];
```

- If `true`, each source file's parse will find the nearest `tsconfig.json` file to that source file.

- This is done by checking that source file's directory tree for the nearest `tsconfig.json`.

- If you use project references, TypeScript will not automatically use project references to resolve files. This means that you will have to add each referenced tsconfig to the `project` field either separately, or via a glob.

- Note that using wide globs `**` in your `parserOptions.project` may cause performance implications. Instead of globs that use `**` to recursively check all folders, prefer paths that use a single `*` at a time. For more info see [#2611](https://github.com/typescript-eslint/typescript-eslint/issues/2611).
Expand Down
5 changes: 3 additions & 2 deletionsdocs/architecture/TypeScript-ESTree.mdx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -174,10 +174,11 @@ interface ParseAndGenerateServicesOptions extends ParseOptions {
preserveNodeMaps?: boolean;

/**
* Absolute (or relative to `tsconfigRootDir`) paths to the tsconfig(s).
* Absolute (or relative to `tsconfigRootDir`) paths to the tsconfig(s),
* or `true` to find the nearest tsconfig.json to the file.
* If this is provided, type information will be returned.
*/
project?: string | string[];
project?: string | string[] | true;

/**
* If you provide a glob (or globs) to the project option, you can use this option to ignore certain folders from
Expand Down
27 changes: 26 additions & 1 deletiondocs/linting/Typed_Linting.mdx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,7 @@ module.exports = {
parser: '@typescript-eslint/parser',
// Added lines start
parserOptions: {
project:['./tsconfig.json'],
project:true,
tsconfigRootDir: __dirname,
},
// Added lines end
Expand All@@ -36,6 +36,31 @@ In more detail:
With that done, run the same lint command you ran before.
You may see new rules reporting errors based on type information!

## Specifying TSConfigs

The `parserOptions.project` option can be turned on with either:

- `true`: to always use `tsconfig.json`s nearest to source files
- `string | string[]`: any number of glob paths to match TSConfig files relative to the

For example, if you use a specific `tsconfig.eslint.json` for linting, you'd specify:

```js title=".eslintrc.js"
module.exports = {
// ...
parserOptions: {
project: './tsconfig.eslint.json',
},
// ...
};
```

See [the `@typescript-eslint/parser` docs for more details](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/README.md#parseroptionsproject).

:::note
If your project is a multi-package monorepo, see [our docs on configuring a monorepo](./typed-linting/Monorepos.mdx).
:::

## FAQs

### How is performance?
Expand Down
2 changes: 1 addition & 1 deletiondocs/linting/typed-linting/Monorepos.mdx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,7 +53,7 @@ module.exports = {
parserOptions: {
tsconfigRootDir: __dirname,
// Remove this line
project:['./tsconfig.json'],
project:true,
// Add this line
project: ['./tsconfig.eslint.json', './packages/*/tsconfig.json'],
},
Expand Down
2 changes: 1 addition & 1 deletionpackages/types/src/parser-options.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -52,7 +52,7 @@ interface ParserOptions {
filePath?: string;
loc?: boolean;
program?: Program;
project?: string | string[];
project?: string | string[] | true;
projectFolderIgnoreList?: (string | RegExp)[];
range?: boolean;
sourceType?: SourceType;
Expand Down
29 changes: 12 additions & 17 deletionspackages/typescript-estree/src/parseSettings/ExpiringCache.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,15 +3,18 @@ import type { CacheDurationSeconds } from '@typescript-eslint/types';
export const DEFAULT_TSCONFIG_CACHE_DURATION_SECONDS = 30;
const ZERO_HR_TIME: [number, number] = [0, 0];

export interface CacheLike<Key, Value> {
get(key: Key): Value | void;
set(key: Key, value: Value): this;
}

/**
* A map with key-level expiration.
*/
export class ExpiringCache<TKey, TValue> {
export class ExpiringCache<TKey, TValue>implements CacheLike<TKey, TValue>{
readonly #cacheDurationSeconds: CacheDurationSeconds;
/**
* The mapping of path-like string to the resolved TSConfig(s)
*/
protected readonly map = new Map<

readonly #map = new Map<
TKey,
Readonly<{
value: TValue;
Expand All@@ -24,7 +27,7 @@ export class ExpiringCache<TKey, TValue> {
}

set(key: TKey, value: TValue): this {
this.map.set(key, {
this.#map.set(key, {
value,
lastSeen:
this.#cacheDurationSeconds === 'Infinity'
Expand All@@ -36,7 +39,7 @@ export class ExpiringCache<TKey, TValue> {
}

get(key: TKey): TValue | undefined {
const entry = this.map.get(key);
const entry = this.#map.get(key);
if (entry?.value != null) {
if (this.#cacheDurationSeconds === 'Infinity') {
return entry.value;
Expand All@@ -48,22 +51,14 @@ export class ExpiringCache<TKey, TValue> {
return entry.value;
} else {
// key has expired - clean it up to free up memory
this.cleanupKey(key);
this.#map.delete(key);
}
}
// no hit :'(
return undefined;
}

protected cleanupKey(key: TKey): void {
this.map.delete(key);
}

get size(): number {
return this.map.size;
}

clear(): void {
this.map.clear();
this.#map.clear();
}
}
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,11 @@ import debug from 'debug';

import { ensureAbsolutePath } from '../create-program/shared';
import type { TSESTreeOptions } from '../parser-options';
import {
DEFAULT_TSCONFIG_CACHE_DURATION_SECONDS,
ExpiringCache,
} from './ExpiringCache';
import { getProjectConfigFiles } from './getProjectConfigFiles';
import type { MutableParseSettings } from './index';
import { inferSingleRun } from './inferSingleRun';
import { resolveProjectList } from './resolveProjectList';
Expand All@@ -11,10 +16,13 @@ const log = debug(
'typescript-eslint:typescript-estree:parser:parseSettings:createParseSettings',
);

let TSCONFIG_MATCH_CACHE: ExpiringCache<string, string> | null;

export function createParseSettings(
code: string,
options: Partial<TSESTreeOptions> = {},
): MutableParseSettings {
const singleRun = inferSingleRun(options);
const tsconfigRootDir =
typeof options.tsconfigRootDir === 'string'
? options.tsconfigRootDir
Expand DownExpand Up@@ -58,8 +66,14 @@ export function createParseSettings(
programs: Array.isArray(options.programs) ? options.programs : null,
projects: [],
range: options.range === true,
singleRun: inferSingleRun(options),
singleRun,
tokens: options.tokens === true ? [] : null,
tsconfigMatchCache: (TSCONFIG_MATCH_CACHE ??= new ExpiringCache(
singleRun
? 'Infinity'
: options.cacheLifetime?.glob ??
DEFAULT_TSCONFIG_CACHE_DURATION_SECONDS,
)),
tsconfigRootDir,
};

Expand DownExpand Up@@ -95,7 +109,7 @@ export function createParseSettings(
if (!parseSettings.programs) {
parseSettings.projects = resolveProjectList({
cacheLifetime: options.cacheLifetime,
project: options.project,
project:getProjectConfigFiles(parseSettings,options.project),
projectFolderIgnoreList: options.projectFolderIgnoreList,
singleRun: parseSettings.singleRun,
tsconfigRootDir: tsconfigRootDir,
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
import debug from 'debug';
import * as fs from 'fs';
import * as path from 'path';

import type { ParseSettings } from '.';

const log = debug('typescript-eslint:typescript-estree:getProjectConfigFiles');

/**
* Checks for a matching TSConfig to a file including its parent directories,
* permanently caching results under each directory it checks.
*
* @remarks
* We don't (yet!) have a way to attach file watchers on disk, but still need to
* cache file checks for rapid subsequent calls to fs.existsSync. See discussion
* in https://github.com/typescript-eslint/typescript-eslint/issues/101.
*/
export function getProjectConfigFiles(
parseSettings: Pick<
ParseSettings,
'filePath' | 'tsconfigMatchCache' | 'tsconfigRootDir'
>,
project: string | string[] | true | undefined,
): string[] | undefined {
if (project !== true) {
return project === undefined || Array.isArray(project)
? project
: [project];
}

log('Looking for tsconfig.json at or above file: %s', parseSettings.filePath);
let directory = path.dirname(parseSettings.filePath);
const checkedDirectories = [directory];

do {
log('Checking tsconfig.json path: %s', directory);
const tsconfigPath = path.join(directory, 'tsconfig.json');
const cached =
parseSettings.tsconfigMatchCache.get(directory) ??
(fs.existsSync(tsconfigPath) && tsconfigPath);

if (cached) {
for (const directory of checkedDirectories) {
parseSettings.tsconfigMatchCache.set(directory, cached);
}
return [cached];
}

directory = path.dirname(directory);
checkedDirectories.push(directory);
} while (
directory.length > 1 &&
directory.length >= parseSettings.tsconfigRootDir.length
);

throw new Error(
`project was set to \`true\` but couldn't find any tsconfig.json relative to '${parseSettings.filePath}' within '${parseSettings.tsconfigRootDir}'.`,
);
}
6 changes: 6 additions & 0 deletionspackages/typescript-estree/src/parseSettings/index.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,7 @@ import type * as ts from 'typescript';

import type { CanonicalPath } from '../create-program/shared';
import type { TSESTree } from '../ts-estree';
import type { CacheLike } from './ExpiringCache';

type DebugModule = 'typescript-eslint' | 'eslint' | 'typescript';

Expand DownExpand Up@@ -115,6 +116,11 @@ export interface MutableParseSettings {
*/
tokens: null | TSESTree.Token[];

/**
* Caches searches for TSConfigs from project directories.
*/
tsconfigMatchCache: CacheLike<string, string>;

/**
* The absolute path to the root directory for all provided `project`s.
*/
Expand Down
5 changes: 3 additions & 2 deletionspackages/typescript-estree/src/parser-options.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -120,10 +120,11 @@ interface ParseAndGenerateServicesOptions extends ParseOptions {
preserveNodeMaps?: boolean;

/**
* Absolute (or relative to `tsconfigRootDir`) paths to the tsconfig(s).
* Absolute (or relative to `tsconfigRootDir`) paths to the tsconfig(s),
* or `true` to find the nearest tsconfig.json to the file.
* If this is provided, type information will be returned.
*/
project?: string | string[];
project?: string | string[] | true;

/**
* If you provide a glob (or globs) to the project option, you can use this option to ignore certain folders from
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
const b = true;
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
const b = true;
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
{
"include": ["."]
}
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
const c = true;
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
import { createParseSettings } from '../../src/parseSettings/createParseSettings';

describe('createParseSettings', () => {
describe('tsconfigMatchCache', () => {
it('reuses the TSConfig match cache when called a subsequent time', () => {
const parseSettings1 = createParseSettings('input.ts');
const parseSettings2 = createParseSettings('input.ts');

expect(parseSettings1.tsconfigMatchCache).toBe(
parseSettings2.tsconfigMatchCache,
);
});
});
});
Loading

[8]ページ先頭

©2009-2025 Movatter.jp