Skip to content

Commit 8f3b0a8

Browse files
authored
fix(typescript-estree): improve missing project file error msg (typescript-eslint#866)
Fixes typescript-eslint#853
1 parent c68e033 commit 8f3b0a8

23 files changed

+190
-38
lines changed

packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,6 @@ foo(str!);
9999
`
100100
declare function a(a: string): any;
101101
declare const b: string | null;
102-
class Mx {
103-
@a(b!)
104-
private prop = 1;
105-
}
106-
`,
107-
`
108102
class Mx {
109103
@a(b!)
110104
private prop = 1;

packages/eslint-plugin/tests/rules/restrict-plus-operands.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,37 +26,37 @@ ruleTester.run('restrict-plus-operands', rule, {
2626
`var foo = BigInt(1) + 1n`,
2727
`var foo = 1n; foo + 2n`,
2828
`
29-
function test () : number { return 2; }
29+
function test(s: string, n: number) : number { return 2; }
3030
var foo = test("5.5", 10) + 10;
31-
`,
31+
`,
3232
`
3333
var x = 5;
3434
var z = 8.2;
3535
var foo = x + z;
36-
`,
36+
`,
3737
`
3838
var w = "6.5";
3939
var y = "10";
4040
var foo = y + w;
41-
`,
41+
`,
4242
'var foo = 1 + 1;',
4343
"var foo = '1' + '1';",
4444
`
4545
var pair: { first: number, second: string } = { first: 5, second: "10" };
4646
var foo = pair.first + 10;
47-
`,
47+
`,
4848
`
4949
var pair: { first: number, second: string } = { first: 5, second: "10" };
5050
var foo = pair.first + (10 as number);
51-
`,
51+
`,
5252
`
5353
var pair: { first: number, second: string } = { first: 5, second: "10" };
5454
var foo = "5.5" + pair.second;
55-
`,
55+
`,
5656
`
5757
var pair: { first: number, second: string } = { first: 5, second: "10" };
5858
var foo = ("5.5" as string) + pair.second;
59-
`,
59+
`,
6060
`const foo = 'hello' + (someBoolean ? 'a' : 'b') + (() => someBoolean ? 'c' : 'd')() + 'e';`,
6161
`const balls = true;`,
6262
`balls === true;`,

packages/parser/README.md

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,25 +52,30 @@ The following additional configuration options are available by specifying them
5252

5353
- Note that if this setting is specified and `createDefaultProgram` is not, you must only lint files that are included in the projects as defined by the provided `tsconfig.json` files. If your existing configuration does not include all of the files you would like to lint, you can create a separate `tsconfig.eslint.json` as follows:
5454

55-
```ts
56-
{
57-
"extends": "./tsconfig.json", // path to existing tsconfig
58-
"include": [
59-
"src/**/*.ts",
60-
"test/**/*.ts",
61-
// etc
62-
]
63-
}
64-
```
55+
```ts
56+
{
57+
// extend your base config so you don't have to redefine your compilerOptions
58+
"extends": "./tsconfig.json",
59+
"include": [
60+
"src/**/*.ts",
61+
"test/**/*.ts",
62+
"typings/**/*.ts",
63+
// etc
64+
65+
// if you have a mixed JS/TS codebase, don't forget to include your JS files
66+
"src/**/*.js"
67+
]
68+
}
69+
```
6570

6671
- **`tsconfigRootDir`** - default `undefined`. This option allows you to provide the root directory for relative tsconfig paths specified in the `project` option above.
6772

68-
- **`createDefaultProgram`** - default `false`. This option allows you to request that when the `project` setting is specified, files will be allowed when not included in the projects defined by the provided `tsconfig.json` files. However, this may incur significant performance costs, so this option is primarily included for backwards-compatibility. See the **`project`** section for more information.
69-
7073
- **`extraFileExtensions`** - default `undefined`. This option allows you to provide one or more additional file extensions which should be considered in the TypeScript Program compilation. E.g. a `.vue` file
7174

7275
- **`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
7376

77+
- **`createDefaultProgram`** - default `false`. This option allows you to request that when the `project` setting is specified, files will be allowed when not included in the projects defined by the provided `tsconfig.json` files. **Using this option will incur significant performance costs. This option is primarily included for backwards-compatibility.** See the **`project`** section above for more information.
78+
7479
### .eslintrc.json
7580

7681
```json

packages/typescript-estree/jest.config.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,12 @@ module.exports = {
1010
collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}'],
1111
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
1212
coverageReporters: ['text-summary', 'lcov'],
13+
globals: {
14+
'ts-jest': {
15+
diagnostics: {
16+
// ignore the diagnostic error for the invalidFileErrors fixtures
17+
ignoreCodes: [5056],
18+
},
19+
},
20+
},
1321
};

packages/typescript-estree/src/convert.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export class Converter {
6767
*/
6868
constructor(ast: ts.SourceFile, options: ConverterOptions) {
6969
this.ast = ast;
70-
this.options = options;
70+
this.options = { ...options };
7171
}
7272

7373
getASTMaps(): ASTMaps {

packages/typescript-estree/src/parser.ts

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import path from 'path';
12
import semver from 'semver';
23
import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports
34
import { astConverter } from './ast-converter';
@@ -9,6 +10,7 @@ import { TSESTree } from './ts-estree';
910
import {
1011
calculateProjectParserOptions,
1112
createProgram,
13+
defaultCompilerOptions,
1214
} from './tsconfig-parser';
1315

1416
/**
@@ -87,9 +89,39 @@ function getASTFromProject(
8789
);
8890

8991
if (!astAndProgram && !createDefaultProgram) {
90-
throw new Error(
91-
`If "parserOptions.project" has been set for @typescript-eslint/parser, ${filePath} must be included in at least one of the projects provided.`,
92-
);
92+
// the file was either not matched within the tsconfig, or the extension wasn't expected
93+
const errorLines = [
94+
'"parserOptions.project" has been set for @typescript-eslint/parser.',
95+
`The file does not match your project config: ${filePath}.`,
96+
];
97+
let hasMatchedAnError = false;
98+
99+
const fileExtension = path.extname(filePath);
100+
if (!['.ts', '.tsx', '.js', '.jsx'].includes(fileExtension)) {
101+
const nonStandardExt = `The extension for the file (${fileExtension}) is non-standard`;
102+
if (extra.extraFileExtensions && extra.extraFileExtensions.length > 0) {
103+
if (!extra.extraFileExtensions.includes(fileExtension)) {
104+
errorLines.push(
105+
`${nonStandardExt}. It should be added to your existing "parserOptions.extraFileExtensions".`,
106+
);
107+
hasMatchedAnError = true;
108+
}
109+
} else {
110+
errorLines.push(
111+
`${nonStandardExt}. You should add "parserOptions.extraFileExtensions" to your config.`,
112+
);
113+
hasMatchedAnError = true;
114+
}
115+
}
116+
117+
if (!hasMatchedAnError) {
118+
errorLines.push(
119+
'The file must be included in at least one of the projects provided.',
120+
);
121+
hasMatchedAnError = true;
122+
}
123+
124+
throw new Error(errorLines.join('\n'));
93125
}
94126

95127
return astAndProgram;
@@ -158,6 +190,7 @@ function createNewProgram(code: string): ASTAndProgram {
158190
noResolve: true,
159191
target: ts.ScriptTarget.Latest,
160192
jsx: extra.jsx ? ts.JsxEmit.Preserve : undefined,
193+
...defaultCompilerOptions,
161194
},
162195
compilerHost,
163196
);

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ import { Extra } from './parser-options';
99
/**
1010
* Default compiler options for program generation from single root file
1111
*/
12-
const defaultCompilerOptions: ts.CompilerOptions = {
12+
export const defaultCompilerOptions: ts.CompilerOptions = {
1313
allowNonTsExtensions: true,
1414
allowJs: true,
15+
checkJs: true,
1516
};
1617

1718
/**
@@ -109,7 +110,7 @@ export function calculateProjectParserOptions(
109110
// create compiler host
110111
const watchCompilerHost = ts.createWatchCompilerHost(
111112
tsconfigPath,
112-
/*optionsToExtend*/ { allowNonTsExtensions: true } as ts.CompilerOptions,
113+
defaultCompilerOptions,
113114
ts.sys,
114115
ts.createSemanticDiagnosticsBuilderProgram,
115116
diagnosticReporter,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export var a = true;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export var a = true;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export var a = true;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export var a = true;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export var a = true;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export var a = true;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export var a = true;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export var a = true;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export var a = true;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export var a = true;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export var a = true;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"include": [
3+
"ts/included.ts",
4+
"ts/included.tsx",
5+
"js/included.js",
6+
"js/included.jsx",
7+
"other/included.vue"
8+
]
9+
}

packages/typescript-estree/tests/lib/__snapshots__/parse.ts.snap

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,42 @@ Object {
189189
}
190190
`;
191191

192+
exports[`parse() invalid file error messages "parserOptions.extraFileExtensions" is non-empty the extension does not match 1`] = `
193+
"\\"parserOptions.project\\" has been set for @typescript-eslint/parser.
194+
The file does not match your project config: tests/fixtures/invalidFileErrors/other/unknownFileType.unknown.
195+
The extension for the file (.unknown) is non-standard. It should be added to your existing \\"parserOptions.extraFileExtensions\\"."
196+
`;
197+
198+
exports[`parse() invalid file error messages "parserOptions.extraFileExtensions" is non-empty the extension matches the file isn't included 1`] = `
199+
"\\"parserOptions.project\\" has been set for @typescript-eslint/parser.
200+
The file does not match your project config: tests/fixtures/invalidFileErrors/other/notIncluded.vue.
201+
The file must be included in at least one of the projects provided."
202+
`;
203+
204+
exports[`parse() invalid file error messages project includes errors for not included files 1`] = `
205+
"\\"parserOptions.project\\" has been set for @typescript-eslint/parser.
206+
The file does not match your project config: tests/fixtures/invalidFileErrors/ts/notIncluded.ts.
207+
The file must be included in at least one of the projects provided."
208+
`;
209+
210+
exports[`parse() invalid file error messages project includes errors for not included files 2`] = `
211+
"\\"parserOptions.project\\" has been set for @typescript-eslint/parser.
212+
The file does not match your project config: tests/fixtures/invalidFileErrors/ts/notIncluded.tsx.
213+
The file must be included in at least one of the projects provided."
214+
`;
215+
216+
exports[`parse() invalid file error messages project includes errors for not included files 3`] = `
217+
"\\"parserOptions.project\\" has been set for @typescript-eslint/parser.
218+
The file does not match your project config: tests/fixtures/invalidFileErrors/js/notIncluded.js.
219+
The file must be included in at least one of the projects provided."
220+
`;
221+
222+
exports[`parse() invalid file error messages project includes errors for not included files 4`] = `
223+
"\\"parserOptions.project\\" has been set for @typescript-eslint/parser.
224+
The file does not match your project config: tests/fixtures/invalidFileErrors/js/notIncluded.jsx.
225+
The file must be included in at least one of the projects provided."
226+
`;
227+
192228
exports[`parse() non string code should correctly convert code to a string for parse() 1`] = `
193229
Object {
194230
"body": Array [

packages/typescript-estree/tests/lib/parse.ts

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
import { join, resolve, relative } from 'path';
12
import * as parser from '../../src/parser';
23
import * as astConverter from '../../src/ast-converter';
34
import { TSESTreeOptions } from '../../src/parser-options';
45
import { createSnapshotTestBlock } from '../../tools/test-utils';
5-
import { join } from 'path';
66

77
const FIXTURES_DIR = './tests/fixtures/simpleProject';
88

@@ -145,7 +145,7 @@ describe('parse()', () => {
145145
};
146146
const projectConfig: TSESTreeOptions = {
147147
...baseConfig,
148-
tsconfigRootDir: join(process.cwd(), FIXTURES_DIR),
148+
tsconfigRootDir: FIXTURES_DIR,
149149
project: './tsconfig.json',
150150
};
151151

@@ -241,4 +241,60 @@ describe('parse()', () => {
241241
).toBeUndefined();
242242
});
243243
});
244+
245+
describe('invalid file error messages', () => {
246+
const PROJECT_DIR = resolve(FIXTURES_DIR, '../invalidFileErrors');
247+
const code = 'var a = true';
248+
const config: TSESTreeOptions = {
249+
comment: true,
250+
tokens: true,
251+
range: true,
252+
loc: true,
253+
tsconfigRootDir: PROJECT_DIR,
254+
project: './tsconfig.json',
255+
extraFileExtensions: ['.vue'],
256+
};
257+
const testParse = (filePath: string) => (): void => {
258+
parser.parseAndGenerateServices(code, {
259+
...config,
260+
filePath: relative(process.cwd(), join(PROJECT_DIR, filePath)),
261+
});
262+
};
263+
264+
describe('project includes', () => {
265+
it("doesn't error for matched files", () => {
266+
expect(testParse('ts/included.ts')).not.toThrow();
267+
expect(testParse('ts/included.tsx')).not.toThrow();
268+
expect(testParse('js/included.js')).not.toThrow();
269+
expect(testParse('js/included.jsx')).not.toThrow();
270+
});
271+
272+
it('errors for not included files', () => {
273+
expect(testParse('ts/notIncluded.ts')).toThrowErrorMatchingSnapshot();
274+
expect(testParse('ts/notIncluded.tsx')).toThrowErrorMatchingSnapshot();
275+
expect(testParse('js/notIncluded.js')).toThrowErrorMatchingSnapshot();
276+
expect(testParse('js/notIncluded.jsx')).toThrowErrorMatchingSnapshot();
277+
});
278+
});
279+
280+
describe('"parserOptions.extraFileExtensions" is non-empty', () => {
281+
describe('the extension matches', () => {
282+
it('the file is included', () => {
283+
expect(testParse('other/included.vue')).not.toThrow();
284+
});
285+
286+
it("the file isn't included", () => {
287+
expect(
288+
testParse('other/notIncluded.vue'),
289+
).toThrowErrorMatchingSnapshot();
290+
});
291+
});
292+
293+
it('the extension does not match', () => {
294+
expect(
295+
testParse('other/unknownFileType.unknown'),
296+
).toThrowErrorMatchingSnapshot();
297+
});
298+
});
299+
});
244300
});

packages/typescript-estree/tests/lib/semanticInfo.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,7 @@ describe('semanticInfo', () => {
236236
`function M() { return Base }`,
237237
createOptions('<input>'),
238238
),
239-
).toThrow(
240-
`If "parserOptions.project" has been set for @typescript-eslint/parser, <input> must be included in at least one of the projects provided.`,
241-
);
239+
).toThrow(/The file does not match your project config: <input>/);
242240
});
243241

244242
it('non-existent project file', () => {

packages/typescript-estree/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
"compilerOptions": {
44
"outDir": "./dist"
55
},
6-
"include": ["src", "tests", "tools"]
6+
"include": ["src", "tests", "tools"],
7+
"exclude": ["tests/fixtures/**/*"]
78
}

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