= $('')
`,
options: [2, { VariableDeclarator: { const: 3 } }],
},
+ // https://github.com/typescript-eslint/typescript-eslint/issues/441
+ `const;`,
],
invalid: [
...individualNodeTests.invalid,
diff --git a/packages/eslint-plugin/tests/rules/no-explicit-any.test.ts b/packages/eslint-plugin/tests/rules/no-explicit-any.test.ts
index cf596ffecbc3..b27cc8111bc0 100644
--- a/packages/eslint-plugin/tests/rules/no-explicit-any.test.ts
+++ b/packages/eslint-plugin/tests/rules/no-explicit-any.test.ts
@@ -1,5 +1,8 @@
-import rule from '../../src/rules/no-explicit-any';
+import rule, { MessageIds, Options } from '../../src/rules/no-explicit-any';
import { RuleTester } from '../RuleTester';
+import { TSESLint } from '@typescript-eslint/experimental-utils';
+
+type InvalidTestCase = TSESLint.InvalidTestCase;
const ruleTester = new RuleTester({
parser: '@typescript-eslint/parser',
@@ -187,7 +190,7 @@ type obj = {
options: [{ ignoreRestArgs: true }],
},
],
- invalid: [
+ invalid: ([
{
code: 'const number: any = 1',
errors: [
@@ -784,5 +787,23 @@ type obj = {
},
],
},
- ],
+ ] as InvalidTestCase[]).reduce((acc, testCase) => {
+ acc.push(testCase);
+ const options = testCase.options || [];
+ const code = `// fixToUnknown: true\n${testCase.code}`;
+ acc.push({
+ code,
+ output: code.replace(/any/g, 'unknown'),
+ options: [{ ...options[0], fixToUnknown: true }],
+ errors: testCase.errors.map(err => {
+ if (err.line === undefined) {
+ return err;
+ }
+
+ return { ...err, line: err.line + 1 };
+ }),
+ });
+
+ return acc;
+ }, []),
});
diff --git a/packages/eslint-plugin/tests/rules/no-triple-slash-reference.test.ts b/packages/eslint-plugin/tests/rules/no-triple-slash-reference.test.ts
index 5beaf104e52b..f120d5262432 100644
--- a/packages/eslint-plugin/tests/rules/no-triple-slash-reference.test.ts
+++ b/packages/eslint-plugin/tests/rules/no-triple-slash-reference.test.ts
@@ -22,7 +22,7 @@ let a
code: '/// ',
errors: [
{
- messageId: 'tripleSlashReference',
+ messageId: 'noTripleSlashReference',
line: 1,
column: 1,
},
@@ -36,7 +36,7 @@ let a
parser: '@typescript-eslint/parser',
errors: [
{
- messageId: 'tripleSlashReference',
+ messageId: 'noTripleSlashReference',
line: 2,
column: 1,
},
diff --git a/packages/eslint-plugin/tests/rules/strict-boolean-expressions.test.ts b/packages/eslint-plugin/tests/rules/strict-boolean-expressions.test.ts
new file mode 100644
index 000000000000..030bade0f480
--- /dev/null
+++ b/packages/eslint-plugin/tests/rules/strict-boolean-expressions.test.ts
@@ -0,0 +1,907 @@
+import path from 'path';
+import rule from '../../src/rules/strict-boolean-expressions';
+import { RuleTester } from '../RuleTester';
+
+const rootPath = path.join(process.cwd(), 'tests/fixtures/');
+
+const ruleTester = new RuleTester({
+ parser: '@typescript-eslint/parser',
+ parserOptions: {
+ tsconfigRootDir: rootPath,
+ project: './tsconfig.json',
+ },
+});
+
+ruleTester.run('strict-boolean-expressions', rule, {
+ valid: [
+ `
+ let val = true;
+ let bool = !val;
+ let bool2 = true || val;
+ let bool3 = true && val;
+ `,
+ `
+ let a = 0;
+ let u1 = typeof a;
+ let u2 = -a;
+ let u3 = ~a;
+ `,
+ `
+ const bool1 = true;
+ const bool2 = false;
+ if (true) {
+ return;
+ }
+
+ if (bool1) {
+ return;
+ }
+
+ if (bool1 && bool2) {
+ return;
+ }
+
+ if (bool1 || bool2) {
+ return;
+ }
+
+ if ((bool1 && bool2) || (bool1 || bool2)) {
+ return;
+ }
+ `,
+ `
+ const bool1 = true;
+ const bool2 = false;
+ const res1 = true ? true : false;
+ const res2 = bool1 && bool2 ? true : false;
+ const res3 = bool1 || bool2 ? true : false;
+ const res4 = (bool1 && bool2) || (bool1 || bool2) ? true : false;
+ `,
+ `
+ for (let i = 0; true; i++) {
+ break;
+ }
+ `,
+ `
+ const bool = true;
+ for (let i = 0; bool; i++) {
+ break;
+ }
+ `,
+ `
+ const bool1 = true;
+ const bool2 = false;
+ for (let i = 0; bool1 && bool2; i++) {
+ break;
+ }
+ `,
+ `
+ const bool1 = true;
+ const bool2 = false;
+ for (let i = 0; bool1 || bool2; i++) {
+ break;
+ }
+ `,
+ `
+ const bool1 = true;
+ const bool2 = false;
+ for (let i = 0; (bool1 && bool2) || (bool1 || bool2); i++) {
+ break;
+ }
+ `,
+ `
+ while (true) {
+ break;
+ }
+ `,
+ `
+ const bool = true;
+ while (bool) {
+ break;
+ }
+ `,
+ `
+ const bool1 = true;
+ const bool2 = false;
+ while (bool1 && bool2) {
+ break;
+ }
+ `,
+ `
+ const bool1 = true;
+ const bool2 = false;
+ while (bool1 || bool2) {
+ break;
+ }
+ `,
+ `
+ const bool1 = true;
+ const bool2 = false;
+ while ((bool1 && bool2) || (bool1 || bool2)) {
+ break;
+ }
+ `,
+ `
+ do {
+ break;
+ } while (true);
+ `,
+ `
+ const bool = true;
+ do {
+ break;
+ } while (bool);
+ `,
+ `
+ const bool1 = true;
+ const bool2 = false;
+ do {
+ break;
+ } while (bool1 && bool2);
+ `,
+ `
+ const bool1 = true;
+ const bool2 = false;
+ do {
+ break;
+ } while (bool1 || bool2);
+ `,
+ `
+ const bool1 = true;
+ const bool2 = false;
+ do {
+ break;
+ } while ((bool1 && bool2) || (bool1 || bool2));
+ `,
+ `
+ function foo(arg: T) { return !arg; }
+ `,
+ ],
+
+ invalid: [
+ {
+ code: `
+ let val = 1;
+ let bool = !val;
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 3,
+ column: 21,
+ },
+ ],
+ },
+ {
+ code: `
+ let val;
+ let bool = !val;
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 3,
+ column: 21,
+ },
+ ],
+ },
+ {
+ code: `
+ let val = 1;
+ let bool = true && val;
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 3,
+ column: 20,
+ },
+ ],
+ },
+ {
+ code: `
+ let val;
+ let bool = true && val;
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 3,
+ column: 20,
+ },
+ ],
+ },
+ {
+ code: `
+ let val = 1;
+ let bool = true || val;
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 3,
+ column: 20,
+ },
+ ],
+ },
+ {
+ code: `
+ let val;
+ let bool = true || val;
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 3,
+ column: 20,
+ },
+ ],
+ },
+ {
+ code: `
+ if (1) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 2,
+ column: 13,
+ },
+ ],
+ },
+ {
+ code: `
+ if (undefined) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 2,
+ column: 13,
+ },
+ ],
+ },
+ {
+ code: `
+ let item = 1;
+ if (item) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 3,
+ column: 13,
+ },
+ ],
+ },
+ {
+ code: `
+ let item;
+ if (item) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 3,
+ column: 13,
+ },
+ ],
+ },
+ {
+ code: `
+ let item1 = true;
+ let item2 = 1;
+ if (item1 && item2) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 13,
+ },
+ ],
+ },
+ {
+ code: `
+ let item1 = 1;
+ let item2 = true;
+ if (item1 && item2) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 13,
+ },
+ ],
+ },
+ {
+ code: `
+ let item1;
+ let item2 = true;
+ if (item1 && item2) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 13,
+ },
+ ],
+ },
+ {
+ code: `
+ let item1 = true;
+ let item2 = 1;
+ if (item1 || item2) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 13,
+ },
+ ],
+ },
+ {
+ code: `
+ let item1 = 1;
+ let item2 = true;
+ if (item1 || item2) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 13,
+ },
+ ],
+ },
+ {
+ code: `
+ let item1;
+ let item2 = true;
+ if (item1 || item2) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 13,
+ },
+ ],
+ },
+ {
+ code: `
+ const bool = 1 ? true : false;
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 2,
+ column: 22,
+ },
+ ],
+ },
+ {
+ code: `
+ const bool = undefined ? true : false;
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 2,
+ column: 22,
+ },
+ ],
+ },
+ {
+ code: `
+ let item = 1;
+ const bool = item ? true : false;
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 3,
+ column: 22,
+ },
+ ],
+ },
+ {
+ code: `
+ let item;
+ const bool = item ? true : false;
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 3,
+ column: 22,
+ },
+ ],
+ },
+ {
+ code: `
+ let item1 = 1;
+ let item2 = false;
+ const bool = item1 && item2 ? true : false;
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 22,
+ },
+ ],
+ },
+ {
+ code: `
+ let item1 = true;
+ let item2 = 1;
+ const bool = item1 && item2 ? true : false;
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 22,
+ },
+ ],
+ },
+ {
+ code: `
+ let item1 = true;
+ let item2;
+ const bool = item1 && item2 ? true : false;
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 22,
+ },
+ ],
+ },
+ {
+ code: `
+ let item1 = 1;
+ let item2 = false;
+ const bool = item1 || item2 ? true : false;
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 22,
+ },
+ ],
+ },
+ {
+ code: `
+ let item1 = true;
+ let item2 = 1;
+ const bool = item1 || item2 ? true : false;
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 22,
+ },
+ ],
+ },
+ {
+ code: `
+ let item1 = true;
+ let item2;
+ const bool = item1 || item2 ? true : false;
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 22,
+ },
+ ],
+ },
+ {
+ code: `
+ for (let i = 0; 1; i++) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 2,
+ column: 25,
+ },
+ ],
+ },
+ {
+ code: `
+ for (let i = 0; undefined; i++) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 2,
+ column: 25,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool = 1;
+ for (let i = 0; bool; i++) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 3,
+ column: 25,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool;
+ for (let i = 0; bool; i++) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 3,
+ column: 25,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool1 = 1;
+ let bool2 = true;
+ for (let i = 0; bool1 && bool2; i++) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 25,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool1;
+ let bool2 = true;
+ for (let i = 0; bool1 && bool2; i++) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 25,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool1 = 1;
+ let bool2 = true;
+ for (let i = 0; bool1 || bool2; i++) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 25,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool1;
+ let bool2 = true;
+ for (let i = 0; bool1 || bool2; i++) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 25,
+ },
+ ],
+ },
+ {
+ code: `
+ while (1) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 2,
+ column: 16,
+ },
+ ],
+ },
+ {
+ code: `
+ while (undefined) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 2,
+ column: 16,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool = 1;
+ while (bool) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 3,
+ column: 16,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool;
+ while (bool) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 3,
+ column: 16,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool1 = 1;
+ let bool2 = true;
+ while (bool1 && bool2) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 16,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool1;
+ let bool2 = true;
+ while (bool1 && bool2) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 16,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool1 = 1;
+ let bool2 = true;
+ while (bool1 || bool2) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 16,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool1;
+ let bool2 = true;
+ while (bool1 || bool2) {
+ return;
+ }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 16,
+ },
+ ],
+ },
+ {
+ code: `
+ do {
+ return;
+ } while (1);
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 18,
+ },
+ ],
+ },
+ {
+ code: `
+ do {
+ return;
+ } while (undefined);
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 4,
+ column: 18,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool = 1;
+ do {
+ return;
+ } while (bool);
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 5,
+ column: 18,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool;
+ do {
+ return;
+ } while (bool);
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 5,
+ column: 18,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool1 = 1;
+ let bool2 = true;
+ do {
+ return;
+ } while (bool1 && bool2);
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 6,
+ column: 18,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool1;
+ let bool2 = true;
+ do {
+ return;
+ } while (bool1 && bool2);
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 6,
+ column: 18,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool1 = 1;
+ let bool2 = true;
+ do {
+ return;
+ } while (bool1 || bool2);
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 6,
+ column: 18,
+ },
+ ],
+ },
+ {
+ code: `
+ let bool1;
+ let bool2 = true;
+ do {
+ return;
+ } while (bool1 || bool2);
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 6,
+ column: 18,
+ },
+ ],
+ },
+ {
+ code: `
+ function foo(arg: T) { return !arg; }
+ `,
+ errors: [
+ {
+ messageId: 'strictBooleanExpression',
+ line: 2,
+ column: 58,
+ },
+ ],
+ },
+ ],
+});
diff --git a/packages/eslint-plugin/tests/rules/triple-slash-reference.test.ts b/packages/eslint-plugin/tests/rules/triple-slash-reference.test.ts
new file mode 100644
index 000000000000..0785bf7a02ee
--- /dev/null
+++ b/packages/eslint-plugin/tests/rules/triple-slash-reference.test.ts
@@ -0,0 +1,128 @@
+import rule from '../../src/rules/triple-slash-reference';
+import { RuleTester } from '../RuleTester';
+
+const ruleTester = new RuleTester({
+ parserOptions: {
+ sourceType: 'module',
+ },
+ parser: '@typescript-eslint/parser',
+});
+
+ruleTester.run('triple-slash-reference', rule, {
+ valid: [
+ {
+ code: `
+ ///
+ ///
+ ///
+ import * as foo from "foo"
+ import * as bar from "bar"
+ import * as baz from "baz"
+ `,
+ options: [{ path: 'always', types: 'always', lib: 'always' }],
+ },
+ {
+ code: `
+ import * as foo from "foo"
+ `,
+ options: [{ path: 'never' }],
+ },
+ {
+ code: `
+ import * as foo from "foo"
+ `,
+ options: [{ types: 'never' }],
+ },
+ {
+ code: `
+ import * as foo from "foo"
+ `,
+ options: [{ lib: 'never' }],
+ },
+ {
+ code: `
+ import * as foo from "foo"
+ `,
+ options: [{ types: 'prefer-import' }],
+ },
+ {
+ code: `
+ ///
+ import * as bar from "bar"
+ `,
+ options: [{ types: 'prefer-import' }],
+ },
+ {
+ code: `
+ /*
+ ///
+ */
+ import * as foo from "foo"
+ `,
+ options: [{ path: 'never', types: 'never', lib: 'never' }],
+ },
+ ],
+ invalid: [
+ {
+ code: `
+///
+import * as foo from "foo"
+ `,
+ options: [{ types: 'prefer-import' }],
+ errors: [
+ {
+ messageId: 'tripleSlashReference',
+ line: 2,
+ column: 1,
+ },
+ ],
+ },
+ {
+ code: `
+///
+import foo = require("foo");
+ `,
+ options: [{ types: 'prefer-import' }],
+ errors: [
+ {
+ messageId: 'tripleSlashReference',
+ line: 2,
+ column: 1,
+ },
+ ],
+ },
+ {
+ code: `/// `,
+ options: [{ path: 'never' }],
+ errors: [
+ {
+ messageId: 'tripleSlashReference',
+ line: 1,
+ column: 1,
+ },
+ ],
+ },
+ {
+ code: `/// `,
+ options: [{ types: 'never' }],
+ errors: [
+ {
+ messageId: 'tripleSlashReference',
+ line: 1,
+ column: 1,
+ },
+ ],
+ },
+ {
+ code: `/// `,
+ options: [{ lib: 'never' }],
+ errors: [
+ {
+ messageId: 'tripleSlashReference',
+ line: 1,
+ column: 1,
+ },
+ ],
+ },
+ ],
+});
diff --git a/packages/typescript-estree/src/ts-estree/ts-estree.ts b/packages/typescript-estree/src/ts-estree/ts-estree.ts
index e786e83e0dfb..8eed48390d0f 100644
--- a/packages/typescript-estree/src/ts-estree/ts-estree.ts
+++ b/packages/typescript-estree/src/ts-estree/ts-estree.ts
@@ -1387,6 +1387,7 @@ export interface UnaryExpression extends UnaryExpressionBase {
export interface VariableDeclaration extends BaseNode {
type: AST_NODE_TYPES.VariableDeclaration;
+ // NOTE - this is not guaranteed to have any elements in it. i.e. `const;`
declarations: VariableDeclarator[];
kind: 'let' | 'const' | 'var';
declare?: boolean;