diff --git a/packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts b/packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts
index 4c06e95a042..4b4e496253f 100644
--- a/packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts
+++ b/packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts
@@ -99,12 +99,6 @@ foo(str!);
`
declare function a(a: string): any;
declare const b: string | null;
-class Mx {
- @a(b!)
- private prop = 1;
-}
- `,
- `
class Mx {
@a(b!)
private prop = 1;
diff --git a/packages/eslint-plugin/tests/rules/restrict-plus-operands.test.ts b/packages/eslint-plugin/tests/rules/restrict-plus-operands.test.ts
index fdda8fe0ef4..44583a202a1 100644
--- a/packages/eslint-plugin/tests/rules/restrict-plus-operands.test.ts
+++ b/packages/eslint-plugin/tests/rules/restrict-plus-operands.test.ts
@@ -26,37 +26,37 @@ ruleTester.run('restrict-plus-operands', rule, {
`var foo = BigInt(1) + 1n`,
`var foo = 1n; foo + 2n`,
`
-function test () : number { return 2; }
+function test(s: string, n: number) : number { return 2; }
var foo = test("5.5", 10) + 10;
- `,
+ `,
`
var x = 5;
var z = 8.2;
var foo = x + z;
- `,
+ `,
`
var w = "6.5";
var y = "10";
var foo = y + w;
- `,
+ `,
'var foo = 1 + 1;',
"var foo = '1' + '1';",
`
var pair: { first: number, second: string } = { first: 5, second: "10" };
var foo = pair.first + 10;
- `,
+ `,
`
var pair: { first: number, second: string } = { first: 5, second: "10" };
var foo = pair.first + (10 as number);
- `,
+ `,
`
var pair: { first: number, second: string } = { first: 5, second: "10" };
var foo = "5.5" + pair.second;
- `,
+ `,
`
var pair: { first: number, second: string } = { first: 5, second: "10" };
var foo = ("5.5" as string) + pair.second;
- `,
+ `,
`const foo = 'hello' + (someBoolean ? 'a' : 'b') + (() => someBoolean ? 'c' : 'd')() + 'e';`,
`const balls = true;`,
`balls === true;`,
diff --git a/packages/parser/README.md b/packages/parser/README.md
index cbabebd95f8..718e2c82ba5 100644
--- a/packages/parser/README.md
+++ b/packages/parser/README.md
@@ -52,25 +52,30 @@ The following additional configuration options are available by specifying them
- 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:
- ```ts
- {
- "extends": "./tsconfig.json", // path to existing tsconfig
- "include": [
- "src/**/*.ts",
- "test/**/*.ts",
- // etc
- ]
- }
- ```
+ ```ts
+ {
+ // extend your base config so you don't have to redefine your compilerOptions
+ "extends": "./tsconfig.json",
+ "include": [
+ "src/**/*.ts",
+ "test/**/*.ts",
+ "typings/**/*.ts",
+ // etc
+
+ // if you have a mixed JS/TS codebase, don't forget to include your JS files
+ "src/**/*.js"
+ ]
+ }
+ ```
- **`tsconfigRootDir`** - default `undefined`. This option allows you to provide the root directory for relative tsconfig paths specified in the `project` option above.
-- **`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.
-
- **`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
- **`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
+- **`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.
+
### .eslintrc.json
```json
diff --git a/packages/typescript-estree/jest.config.js b/packages/typescript-estree/jest.config.js
index 4005947d277..e01f6ed0775 100644
--- a/packages/typescript-estree/jest.config.js
+++ b/packages/typescript-estree/jest.config.js
@@ -10,4 +10,12 @@ module.exports = {
collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}'],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
coverageReporters: ['text-summary', 'lcov'],
+ globals: {
+ 'ts-jest': {
+ diagnostics: {
+ // ignore the diagnostic error for the invalidFileErrors fixtures
+ ignoreCodes: [5056],
+ },
+ },
+ },
};
diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts
index 3a7d2de99dc..43ab7889c6b 100644
--- a/packages/typescript-estree/src/convert.ts
+++ b/packages/typescript-estree/src/convert.ts
@@ -67,7 +67,7 @@ export class Converter {
*/
constructor(ast: ts.SourceFile, options: ConverterOptions) {
this.ast = ast;
- this.options = options;
+ this.options = { ...options };
}
getASTMaps(): ASTMaps {
diff --git a/packages/typescript-estree/src/parser.ts b/packages/typescript-estree/src/parser.ts
index f215fa44492..1b89136928a 100644
--- a/packages/typescript-estree/src/parser.ts
+++ b/packages/typescript-estree/src/parser.ts
@@ -1,3 +1,4 @@
+import path from 'path';
import semver from 'semver';
import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports
import { astConverter } from './ast-converter';
@@ -9,6 +10,7 @@ import { TSESTree } from './ts-estree';
import {
calculateProjectParserOptions,
createProgram,
+ defaultCompilerOptions,
} from './tsconfig-parser';
/**
@@ -87,9 +89,39 @@ function getASTFromProject(
);
if (!astAndProgram && !createDefaultProgram) {
- throw new Error(
- `If "parserOptions.project" has been set for @typescript-eslint/parser, ${filePath} must be included in at least one of the projects provided.`,
- );
+ // the file was either not matched within the tsconfig, or the extension wasn't expected
+ const errorLines = [
+ '"parserOptions.project" has been set for @typescript-eslint/parser.',
+ `The file does not match your project config: ${filePath}.`,
+ ];
+ let hasMatchedAnError = false;
+
+ const fileExtension = path.extname(filePath);
+ if (!['.ts', '.tsx', '.js', '.jsx'].includes(fileExtension)) {
+ const nonStandardExt = `The extension for the file (${fileExtension}) is non-standard`;
+ if (extra.extraFileExtensions && extra.extraFileExtensions.length > 0) {
+ if (!extra.extraFileExtensions.includes(fileExtension)) {
+ errorLines.push(
+ `${nonStandardExt}. It should be added to your existing "parserOptions.extraFileExtensions".`,
+ );
+ hasMatchedAnError = true;
+ }
+ } else {
+ errorLines.push(
+ `${nonStandardExt}. You should add "parserOptions.extraFileExtensions" to your config.`,
+ );
+ hasMatchedAnError = true;
+ }
+ }
+
+ if (!hasMatchedAnError) {
+ errorLines.push(
+ 'The file must be included in at least one of the projects provided.',
+ );
+ hasMatchedAnError = true;
+ }
+
+ throw new Error(errorLines.join('\n'));
}
return astAndProgram;
@@ -158,6 +190,7 @@ function createNewProgram(code: string): ASTAndProgram {
noResolve: true,
target: ts.ScriptTarget.Latest,
jsx: extra.jsx ? ts.JsxEmit.Preserve : undefined,
+ ...defaultCompilerOptions,
},
compilerHost,
);
diff --git a/packages/typescript-estree/src/tsconfig-parser.ts b/packages/typescript-estree/src/tsconfig-parser.ts
index 88c63171545..affbe090627 100644
--- a/packages/typescript-estree/src/tsconfig-parser.ts
+++ b/packages/typescript-estree/src/tsconfig-parser.ts
@@ -9,9 +9,10 @@ import { Extra } from './parser-options';
/**
* Default compiler options for program generation from single root file
*/
-const defaultCompilerOptions: ts.CompilerOptions = {
+export const defaultCompilerOptions: ts.CompilerOptions = {
allowNonTsExtensions: true,
allowJs: true,
+ checkJs: true,
};
/**
@@ -109,7 +110,7 @@ export function calculateProjectParserOptions(
// create compiler host
const watchCompilerHost = ts.createWatchCompilerHost(
tsconfigPath,
- /*optionsToExtend*/ { allowNonTsExtensions: true } as ts.CompilerOptions,
+ defaultCompilerOptions,
ts.sys,
ts.createSemanticDiagnosticsBuilderProgram,
diagnosticReporter,
diff --git a/packages/typescript-estree/tests/fixtures/invalidFileErrors/js/included.js b/packages/typescript-estree/tests/fixtures/invalidFileErrors/js/included.js
new file mode 100644
index 00000000000..25005f98f8f
--- /dev/null
+++ b/packages/typescript-estree/tests/fixtures/invalidFileErrors/js/included.js
@@ -0,0 +1 @@
+export var a = true;
diff --git a/packages/typescript-estree/tests/fixtures/invalidFileErrors/js/included.jsx b/packages/typescript-estree/tests/fixtures/invalidFileErrors/js/included.jsx
new file mode 100644
index 00000000000..25005f98f8f
--- /dev/null
+++ b/packages/typescript-estree/tests/fixtures/invalidFileErrors/js/included.jsx
@@ -0,0 +1 @@
+export var a = true;
diff --git a/packages/typescript-estree/tests/fixtures/invalidFileErrors/js/notIncluded.js b/packages/typescript-estree/tests/fixtures/invalidFileErrors/js/notIncluded.js
new file mode 100644
index 00000000000..25005f98f8f
--- /dev/null
+++ b/packages/typescript-estree/tests/fixtures/invalidFileErrors/js/notIncluded.js
@@ -0,0 +1 @@
+export var a = true;
diff --git a/packages/typescript-estree/tests/fixtures/invalidFileErrors/js/notIncluded.jsx b/packages/typescript-estree/tests/fixtures/invalidFileErrors/js/notIncluded.jsx
new file mode 100644
index 00000000000..25005f98f8f
--- /dev/null
+++ b/packages/typescript-estree/tests/fixtures/invalidFileErrors/js/notIncluded.jsx
@@ -0,0 +1 @@
+export var a = true;
diff --git a/packages/typescript-estree/tests/fixtures/invalidFileErrors/other/included.vue b/packages/typescript-estree/tests/fixtures/invalidFileErrors/other/included.vue
new file mode 100644
index 00000000000..25005f98f8f
--- /dev/null
+++ b/packages/typescript-estree/tests/fixtures/invalidFileErrors/other/included.vue
@@ -0,0 +1 @@
+export var a = true;
diff --git a/packages/typescript-estree/tests/fixtures/invalidFileErrors/other/notIncluded.vue b/packages/typescript-estree/tests/fixtures/invalidFileErrors/other/notIncluded.vue
new file mode 100644
index 00000000000..25005f98f8f
--- /dev/null
+++ b/packages/typescript-estree/tests/fixtures/invalidFileErrors/other/notIncluded.vue
@@ -0,0 +1 @@
+export var a = true;
diff --git a/packages/typescript-estree/tests/fixtures/invalidFileErrors/other/unknownFileType.unknown b/packages/typescript-estree/tests/fixtures/invalidFileErrors/other/unknownFileType.unknown
new file mode 100644
index 00000000000..25005f98f8f
--- /dev/null
+++ b/packages/typescript-estree/tests/fixtures/invalidFileErrors/other/unknownFileType.unknown
@@ -0,0 +1 @@
+export var a = true;
diff --git a/packages/typescript-estree/tests/fixtures/invalidFileErrors/ts/included.ts b/packages/typescript-estree/tests/fixtures/invalidFileErrors/ts/included.ts
new file mode 100644
index 00000000000..25005f98f8f
--- /dev/null
+++ b/packages/typescript-estree/tests/fixtures/invalidFileErrors/ts/included.ts
@@ -0,0 +1 @@
+export var a = true;
diff --git a/packages/typescript-estree/tests/fixtures/invalidFileErrors/ts/included.tsx b/packages/typescript-estree/tests/fixtures/invalidFileErrors/ts/included.tsx
new file mode 100644
index 00000000000..25005f98f8f
--- /dev/null
+++ b/packages/typescript-estree/tests/fixtures/invalidFileErrors/ts/included.tsx
@@ -0,0 +1 @@
+export var a = true;
diff --git a/packages/typescript-estree/tests/fixtures/invalidFileErrors/ts/notIncluded.ts b/packages/typescript-estree/tests/fixtures/invalidFileErrors/ts/notIncluded.ts
new file mode 100644
index 00000000000..25005f98f8f
--- /dev/null
+++ b/packages/typescript-estree/tests/fixtures/invalidFileErrors/ts/notIncluded.ts
@@ -0,0 +1 @@
+export var a = true;
diff --git a/packages/typescript-estree/tests/fixtures/invalidFileErrors/ts/notIncluded.tsx b/packages/typescript-estree/tests/fixtures/invalidFileErrors/ts/notIncluded.tsx
new file mode 100644
index 00000000000..25005f98f8f
--- /dev/null
+++ b/packages/typescript-estree/tests/fixtures/invalidFileErrors/ts/notIncluded.tsx
@@ -0,0 +1 @@
+export var a = true;
diff --git a/packages/typescript-estree/tests/fixtures/invalidFileErrors/tsconfig.json b/packages/typescript-estree/tests/fixtures/invalidFileErrors/tsconfig.json
new file mode 100644
index 00000000000..de5d69d736c
--- /dev/null
+++ b/packages/typescript-estree/tests/fixtures/invalidFileErrors/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "include": [
+ "ts/included.ts",
+ "ts/included.tsx",
+ "js/included.js",
+ "js/included.jsx",
+ "other/included.vue"
+ ]
+}
diff --git a/packages/typescript-estree/tests/lib/__snapshots__/parse.ts.snap b/packages/typescript-estree/tests/lib/__snapshots__/parse.ts.snap
index 38e378d9f7e..bca89ec8d8c 100644
--- a/packages/typescript-estree/tests/lib/__snapshots__/parse.ts.snap
+++ b/packages/typescript-estree/tests/lib/__snapshots__/parse.ts.snap
@@ -189,6 +189,42 @@ Object {
}
`;
+exports[`parse() invalid file error messages "parserOptions.extraFileExtensions" is non-empty the extension does not match 1`] = `
+"\\"parserOptions.project\\" has been set for @typescript-eslint/parser.
+The file does not match your project config: tests/fixtures/invalidFileErrors/other/unknownFileType.unknown.
+The extension for the file (.unknown) is non-standard. It should be added to your existing \\"parserOptions.extraFileExtensions\\"."
+`;
+
+exports[`parse() invalid file error messages "parserOptions.extraFileExtensions" is non-empty the extension matches the file isn't included 1`] = `
+"\\"parserOptions.project\\" has been set for @typescript-eslint/parser.
+The file does not match your project config: tests/fixtures/invalidFileErrors/other/notIncluded.vue.
+The file must be included in at least one of the projects provided."
+`;
+
+exports[`parse() invalid file error messages project includes errors for not included files 1`] = `
+"\\"parserOptions.project\\" has been set for @typescript-eslint/parser.
+The file does not match your project config: tests/fixtures/invalidFileErrors/ts/notIncluded.ts.
+The file must be included in at least one of the projects provided."
+`;
+
+exports[`parse() invalid file error messages project includes errors for not included files 2`] = `
+"\\"parserOptions.project\\" has been set for @typescript-eslint/parser.
+The file does not match your project config: tests/fixtures/invalidFileErrors/ts/notIncluded.tsx.
+The file must be included in at least one of the projects provided."
+`;
+
+exports[`parse() invalid file error messages project includes errors for not included files 3`] = `
+"\\"parserOptions.project\\" has been set for @typescript-eslint/parser.
+The file does not match your project config: tests/fixtures/invalidFileErrors/js/notIncluded.js.
+The file must be included in at least one of the projects provided."
+`;
+
+exports[`parse() invalid file error messages project includes errors for not included files 4`] = `
+"\\"parserOptions.project\\" has been set for @typescript-eslint/parser.
+The file does not match your project config: tests/fixtures/invalidFileErrors/js/notIncluded.jsx.
+The file must be included in at least one of the projects provided."
+`;
+
exports[`parse() non string code should correctly convert code to a string for parse() 1`] = `
Object {
"body": Array [
diff --git a/packages/typescript-estree/tests/lib/parse.ts b/packages/typescript-estree/tests/lib/parse.ts
index 57a4bc05742..6ed8db76cbc 100644
--- a/packages/typescript-estree/tests/lib/parse.ts
+++ b/packages/typescript-estree/tests/lib/parse.ts
@@ -1,8 +1,8 @@
+import { join, resolve, relative } from 'path';
import * as parser from '../../src/parser';
import * as astConverter from '../../src/ast-converter';
import { TSESTreeOptions } from '../../src/parser-options';
import { createSnapshotTestBlock } from '../../tools/test-utils';
-import { join } from 'path';
const FIXTURES_DIR = './tests/fixtures/simpleProject';
@@ -145,7 +145,7 @@ describe('parse()', () => {
};
const projectConfig: TSESTreeOptions = {
...baseConfig,
- tsconfigRootDir: join(process.cwd(), FIXTURES_DIR),
+ tsconfigRootDir: FIXTURES_DIR,
project: './tsconfig.json',
};
@@ -241,4 +241,60 @@ describe('parse()', () => {
).toBeUndefined();
});
});
+
+ describe('invalid file error messages', () => {
+ const PROJECT_DIR = resolve(FIXTURES_DIR, '../invalidFileErrors');
+ const code = 'var a = true';
+ const config: TSESTreeOptions = {
+ comment: true,
+ tokens: true,
+ range: true,
+ loc: true,
+ tsconfigRootDir: PROJECT_DIR,
+ project: './tsconfig.json',
+ extraFileExtensions: ['.vue'],
+ };
+ const testParse = (filePath: string) => (): void => {
+ parser.parseAndGenerateServices(code, {
+ ...config,
+ filePath: relative(process.cwd(), join(PROJECT_DIR, filePath)),
+ });
+ };
+
+ describe('project includes', () => {
+ it("doesn't error for matched files", () => {
+ expect(testParse('ts/included.ts')).not.toThrow();
+ expect(testParse('ts/included.tsx')).not.toThrow();
+ expect(testParse('js/included.js')).not.toThrow();
+ expect(testParse('js/included.jsx')).not.toThrow();
+ });
+
+ it('errors for not included files', () => {
+ expect(testParse('ts/notIncluded.ts')).toThrowErrorMatchingSnapshot();
+ expect(testParse('ts/notIncluded.tsx')).toThrowErrorMatchingSnapshot();
+ expect(testParse('js/notIncluded.js')).toThrowErrorMatchingSnapshot();
+ expect(testParse('js/notIncluded.jsx')).toThrowErrorMatchingSnapshot();
+ });
+ });
+
+ describe('"parserOptions.extraFileExtensions" is non-empty', () => {
+ describe('the extension matches', () => {
+ it('the file is included', () => {
+ expect(testParse('other/included.vue')).not.toThrow();
+ });
+
+ it("the file isn't included", () => {
+ expect(
+ testParse('other/notIncluded.vue'),
+ ).toThrowErrorMatchingSnapshot();
+ });
+ });
+
+ it('the extension does not match', () => {
+ expect(
+ testParse('other/unknownFileType.unknown'),
+ ).toThrowErrorMatchingSnapshot();
+ });
+ });
+ });
});
diff --git a/packages/typescript-estree/tests/lib/semanticInfo.ts b/packages/typescript-estree/tests/lib/semanticInfo.ts
index 1afab0c5e44..157edec7412 100644
--- a/packages/typescript-estree/tests/lib/semanticInfo.ts
+++ b/packages/typescript-estree/tests/lib/semanticInfo.ts
@@ -236,9 +236,7 @@ describe('semanticInfo', () => {
`function M() { return Base }`,
createOptions(''),
),
- ).toThrow(
- `If "parserOptions.project" has been set for @typescript-eslint/parser, must be included in at least one of the projects provided.`,
- );
+ ).toThrow(/The file does not match your project config: /);
});
it('non-existent project file', () => {
diff --git a/packages/typescript-estree/tsconfig.json b/packages/typescript-estree/tsconfig.json
index e389d7edef3..2ea9199d263 100644
--- a/packages/typescript-estree/tsconfig.json
+++ b/packages/typescript-estree/tsconfig.json
@@ -3,5 +3,6 @@
"compilerOptions": {
"outDir": "./dist"
},
- "include": ["src", "tests", "tools"]
+ "include": ["src", "tests", "tools"],
+ "exclude": ["tests/fixtures/**/*"]
}