Skip to content

Commit 1e29e69

Browse files
authored
feat(typescript-estree): add option to ignore certain folders from glob resolution (typescript-eslint#1802)
1 parent 7d963fd commit 1e29e69

File tree

11 files changed

+213
-64
lines changed

11 files changed

+213
-64
lines changed

packages/experimental-utils/src/ts-eslint/ParserOptions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ interface ParserOptions {
1616
loc?: boolean;
1717
noWatch?: boolean;
1818
project?: string | string[];
19+
projectFolderIgnoreList?: (string | RegExp)[];
1920
range?: boolean;
2021
sourceType?: 'script' | 'module';
2122
tokens?: boolean;

packages/parser/README.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ interface ParserOptions {
5454
jsx?: boolean;
5555
};
5656
project?: string | string[];
57+
projectFolderIgnoreList?: (string | RegExp)[];
5758
tsconfigRootDir?: string;
5859
extraFileExtensions?: string[];
5960
warnOnUnsupportedTypeScriptVersion?: boolean;
@@ -118,26 +119,36 @@ This option allows you to provide a path to your project's `tsconfig.json`. **Th
118119
}
119120
```
120121

121-
### `tsconfigRootDir`
122+
### `parserOptions.tsconfigRootDir`
122123

123124
Default `undefined`.
124125

125126
This option allows you to provide the root directory for relative tsconfig paths specified in the `project` option above.
126127

127-
### `extraFileExtensions`
128+
### `parserOptions.projectFolderIgnoreList`
129+
130+
Default `["/node_modules/"]`.
131+
132+
This option allows you to ignore folders from being included in your provided list of `project`s.
133+
Any resolved project path that matches one or more of the provided regular expressions will be removed from the list.
134+
This is useful if you have configured glob patterns, but want to make sure you ignore certain folders.
135+
136+
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).
137+
138+
### `parserOptions.extraFileExtensions`
128139

129140
Default `undefined`.
130141

131142
This option allows you to provide one or more additional file extensions which should be considered in the TypeScript Program compilation.
132143
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"]`.
133144

134-
### `warnOnUnsupportedTypeScriptVersion`
145+
### `parserOptions.warnOnUnsupportedTypeScriptVersion`
135146

136147
Default `true`.
137148

138149
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
139150

140-
### `createDefaultProgram`
151+
### `parserOptions.createDefaultProgram`
141152

142153
Default `false`.
143154

packages/typescript-estree/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,16 @@ interface ParseAndGenerateServicesOptions extends ParseOptions {
182182
*/
183183
project?: string | string[];
184184

185+
/**
186+
* If you provide a glob (or globs) to the project option, you can use this option to blacklist
187+
* certain folders from being matched by the globs.
188+
* Any project path that matches one or more of the provided regular expressions will be removed from the list.
189+
*
190+
* Accepts an array of strings that are passed to new RegExp(), or an array of regular expressions.
191+
* By default, this is set to ["/node_modules/"]
192+
*/
193+
projectFolderIgnoreList?: (string | RegExp)[];
194+
185195
/**
186196
* The absolute path to the root directory for all provided `project`s.
187197
*/
@@ -205,6 +215,7 @@ const PARSE_AND_GENERATE_SERVICES_DEFAULT_OPTIONS: ParseOptions = {
205215
extraFileExtensions: [],
206216
preserveNodeMaps: false, // or true, if you do not set this, but pass `project`
207217
project: undefined,
218+
projectFolderIgnoreList: ['/node_modules/'],
208219
tsconfigRootDir: process.cwd(),
209220
};
210221

packages/typescript-estree/src/parser-options.ts

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -29,28 +29,23 @@ export interface Extra {
2929
// MAKE SURE THIS IS KEPT IN SYNC WITH THE README //
3030
////////////////////////////////////////////////////
3131

32-
export interface TSESTreeOptions {
32+
interface ParseOptions {
3333
/**
3434
* create a top-level comments array containing all comments
3535
*/
3636
comment?: boolean;
3737

3838
/**
39-
* For convenience:
40-
* - true === ['typescript-eslint']
41-
* - false === []
42-
*
4339
* An array of modules to turn explicit debugging on for.
4440
* - 'typescript-eslint' is the same as setting the env var `DEBUG=typescript-eslint:*`
4541
* - 'eslint' is the same as setting the env var `DEBUG=eslint:*`
4642
* - 'typescript' is the same as setting `extendedDiagnostics: true` in your tsconfig compilerOptions
43+
*
44+
* For convenience, also supports a boolean:
45+
* - true === ['typescript-eslint']
46+
* - false === []
4747
*/
48-
debugLevel?: boolean | DebugModule[];
49-
50-
/**
51-
* Causes the parser to error if the TypeScript compiler returns any unexpected syntax/semantic errors.
52-
*/
53-
errorOnTypeScriptSyntacticAndSemanticIssues?: boolean;
48+
debugLevel?: boolean | ('typescript-eslint' | 'eslint' | 'typescript')[];
5449

5550
/**
5651
* Cause the parser to error if it encounters an unknown AST node type (useful for testing).
@@ -59,14 +54,7 @@ export interface TSESTreeOptions {
5954
errorOnUnknownASTType?: boolean;
6055

6156
/**
62-
* When `project` is provided, this controls the non-standard file extensions which will be parsed.
63-
* It accepts an array of file extensions, each preceded by a `.`.
64-
*/
65-
extraFileExtensions?: string[];
66-
67-
/**
68-
* Absolute (or relative to `tsconfigRootDir`) path to the file being parsed.
69-
* When `project` is provided, this is required, as it is used to fetch the file from the TypeScript compiler's cache.
57+
* Absolute (or relative to `cwd`) path to the file being parsed.
7058
*/
7159
filePath?: string;
7260

@@ -95,6 +83,45 @@ export interface TSESTreeOptions {
9583
*/
9684
loggerFn?: Function | false;
9785

86+
/**
87+
* Controls whether the `range` property is included on AST nodes.
88+
* The `range` property is a [number, number] which indicates the start/end index of the node in the file contents.
89+
* This is similar to the `loc` property, except this is the absolute index.
90+
*/
91+
range?: boolean;
92+
93+
/**
94+
* Set to true to create a top-level array containing all tokens from the file.
95+
*/
96+
tokens?: boolean;
97+
98+
/*
99+
* The JSX AST changed the node type for string literals
100+
* inside a JSX Element from `Literal` to `JSXText`.
101+
* When value is `true`, these nodes will be parsed as type `JSXText`.
102+
* When value is `false`, these nodes will be parsed as type `Literal`.
103+
*/
104+
useJSXTextNode?: boolean;
105+
}
106+
107+
interface ParseAndGenerateServicesOptions extends ParseOptions {
108+
/**
109+
* Causes the parser to error if the TypeScript compiler returns any unexpected syntax/semantic errors.
110+
*/
111+
errorOnTypeScriptSyntacticAndSemanticIssues?: boolean;
112+
113+
/**
114+
* When `project` is provided, this controls the non-standard file extensions which will be parsed.
115+
* It accepts an array of file extensions, each preceded by a `.`.
116+
*/
117+
extraFileExtensions?: string[];
118+
119+
/**
120+
* Absolute (or relative to `tsconfigRootDir`) path to the file being parsed.
121+
* When `project` is provided, this is required, as it is used to fetch the file from the TypeScript compiler's cache.
122+
*/
123+
filePath?: string;
124+
98125
/**
99126
* Allows the user to control whether or not two-way AST node maps are preserved
100127
* during the AST conversion process.
@@ -114,30 +141,20 @@ export interface TSESTreeOptions {
114141
project?: string | string[];
115142

116143
/**
117-
* Controls whether the `range` property is included on AST nodes.
118-
* The `range` property is a [number, number] which indicates the start/end index of the node in the file contents.
119-
* This is similar to the `loc` property, except this is the absolute index.
120-
*/
121-
range?: boolean;
122-
123-
/**
124-
* Set to true to create a top-level array containing all tokens from the file.
144+
* If you provide a glob (or globs) to the project option, you can use this option to blacklist
145+
* certain folders from being matched by the globs.
146+
* Any project path that matches one or more of the provided regular expressions will be removed from the list.
147+
*
148+
* Accepts an array of strings that are passed to new RegExp(), or an array of regular expressions.
149+
* By default, this is set to ["/node_modules/"]
125150
*/
126-
tokens?: boolean;
151+
projectFolderIgnoreList?: (string | RegExp)[];
127152

128153
/**
129154
* The absolute path to the root directory for all provided `project`s.
130155
*/
131156
tsconfigRootDir?: string;
132157

133-
/*
134-
* The JSX AST changed the node type for string literals
135-
* inside a JSX Element from `Literal` to `JSXText`.
136-
* When value is `true`, these nodes will be parsed as type `JSXText`.
137-
* When value is `false`, these nodes will be parsed as type `Literal`.
138-
*/
139-
useJSXTextNode?: boolean;
140-
141158
/**
142159
***************************************************************************************
143160
* IT IS RECOMMENDED THAT YOU DO NOT USE THIS OPTION, AS IT CAUSES PERFORMANCE ISSUES. *
@@ -150,6 +167,8 @@ export interface TSESTreeOptions {
150167
createDefaultProgram?: boolean;
151168
}
152169

170+
export type TSESTreeOptions = ParseAndGenerateServicesOptions;
171+
153172
// This lets us use generics to type the return value, and removes the need to
154173
// handle the undefined type in the get method
155174
export interface ParserWeakMap<TKey, TValueBase> {

packages/typescript-estree/src/parser.ts

Lines changed: 77 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import { getFirstSemanticOrSyntacticError } from './semantic-or-syntactic-errors
1414
import { TSESTree } from './ts-estree';
1515
import { ensureAbsolutePath } from './create-program/shared';
1616

17+
const log = debug('typescript-eslint:typescript-estree:parser');
18+
1719
/**
1820
* This needs to be kept in sync with the top-level README.md in the
1921
* typescript-eslint monorepo
@@ -111,6 +113,74 @@ function resetExtra(): void {
111113
};
112114
}
113115

116+
/**
117+
* Normalizes, sanitizes, resolves and filters the provided
118+
*/
119+
function prepareAndTransformProjects(
120+
projectsInput: string | string[] | undefined,
121+
ignoreListInput: (string | RegExp)[] | undefined,
122+
): string[] {
123+
let projects: string[] = [];
124+
125+
// Normalize and sanitize the project paths
126+
if (typeof projectsInput === 'string') {
127+
projects.push(projectsInput);
128+
} else if (Array.isArray(projectsInput)) {
129+
for (const project of projectsInput) {
130+
if (typeof project === 'string') {
131+
projects.push(project);
132+
}
133+
}
134+
}
135+
136+
if (projects.length === 0) {
137+
return projects;
138+
}
139+
140+
// Transform glob patterns into paths
141+
projects = projects.reduce<string[]>(
142+
(projects, project) =>
143+
projects.concat(
144+
isGlob(project)
145+
? globSync(project, {
146+
cwd: extra.tsconfigRootDir,
147+
})
148+
: project,
149+
),
150+
[],
151+
);
152+
153+
// Normalize and sanitize the ignore regex list
154+
const ignoreRegexes: RegExp[] = [];
155+
if (Array.isArray(ignoreListInput)) {
156+
for (const ignore of ignoreListInput) {
157+
if (ignore instanceof RegExp) {
158+
ignoreRegexes.push(ignore);
159+
} else if (typeof ignore === 'string') {
160+
ignoreRegexes.push(new RegExp(ignore));
161+
}
162+
}
163+
} else {
164+
ignoreRegexes.push(/\/node_modules\//);
165+
}
166+
167+
// Remove any paths that match the ignore list
168+
const filtered = projects.filter(project => {
169+
for (const ignore of ignoreRegexes) {
170+
if (ignore.test(project)) {
171+
return false;
172+
}
173+
}
174+
175+
return true;
176+
});
177+
178+
log('parserOptions.project matched projects: %s', projects);
179+
log('ignore list applied to parserOptions.project: %s', filtered);
180+
181+
return filtered;
182+
}
183+
114184
function applyParserOptionsToExtra(options: TSESTreeOptions): void {
115185
/**
116186
* Configure Debug logging
@@ -205,34 +275,18 @@ function applyParserOptionsToExtra(options: TSESTreeOptions): void {
205275
extra.log = Function.prototype;
206276
}
207277

208-
if (typeof options.project === 'string') {
209-
extra.projects = [options.project];
210-
} else if (
211-
Array.isArray(options.project) &&
212-
options.project.every(projectPath => typeof projectPath === 'string')
213-
) {
214-
extra.projects = options.project;
215-
}
216-
217278
if (typeof options.tsconfigRootDir === 'string') {
218279
extra.tsconfigRootDir = options.tsconfigRootDir;
219280
}
281+
282+
// NOTE - ensureAbsolutePath relies upon having the correct tsconfigRootDir in extra
220283
extra.filePath = ensureAbsolutePath(extra.filePath, extra);
221284

222-
// Transform glob patterns into paths
223-
if (extra.projects) {
224-
extra.projects = extra.projects.reduce<string[]>(
225-
(projects, project) =>
226-
projects.concat(
227-
isGlob(project)
228-
? globSync(project, {
229-
cwd: extra.tsconfigRootDir || process.cwd(),
230-
})
231-
: project,
232-
),
233-
[],
234-
);
235-
}
285+
// NOTE - prepareAndTransformProjects relies upon having the correct tsconfigRootDir in extra
286+
extra.projects = prepareAndTransformProjects(
287+
options.project,
288+
options.projectFolderIgnoreList,
289+
);
236290

237291
if (
238292
Array.isArray(options.extraFileExtensions) &&
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const x = 1;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"include": ["./file.ts"]
3+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const x = 2;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"include": ["./file.ts"]
3+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy