({
// `.catch()` that handles the promise.
return (
!isPromiseCatchCallWithHandler(node) &&
- !isPromiseThenCallWithRejectionHandler(node)
+ !isPromiseThenCallWithRejectionHandler(node) &&
+ !isPromiseFinallyCallWithHandler(node)
);
} else if (ts.isConditionalExpression(node)) {
// We must be getting the promise-like value from one of the branches of the
@@ -216,3 +217,13 @@ function isPromiseThenCallWithRejectionHandler(
expression.arguments.length >= 2
);
}
+
+function isPromiseFinallyCallWithHandler(
+ expression: ts.CallExpression,
+): boolean {
+ return (
+ tsutils.isPropertyAccessExpression(expression.expression) &&
+ expression.expression.name.text === 'finally' &&
+ expression.arguments.length >= 1
+ );
+}
diff --git a/packages/eslint-plugin/src/rules/return-await.ts b/packages/eslint-plugin/src/rules/return-await.ts
index f77d80fe5d40..d18e41ef00e0 100644
--- a/packages/eslint-plugin/src/rules/return-await.ts
+++ b/packages/eslint-plugin/src/rules/return-await.ts
@@ -1,6 +1,7 @@
import {
AST_NODE_TYPES,
TSESTree,
+ TSESLint,
} from '@typescript-eslint/experimental-utils';
import * as tsutils from 'tsutils';
import * as ts from 'typescript';
@@ -16,6 +17,7 @@ export default util.createRule({
requiresTypeChecking: true,
extendsBaseRule: 'no-return-await',
},
+ fixable: 'code',
type: 'problem',
messages: {
nonPromiseAwait:
@@ -36,6 +38,7 @@ export default util.createRule({
create(context, [option]) {
const parserServices = util.getParserServices(context);
const checker = parserServices.program.getTypeChecker();
+ const sourceCode = context.getSourceCode();
function inTryCatch(node: ts.Node): boolean {
let ancestor = node.parent;
@@ -54,13 +57,66 @@ export default util.createRule({
return false;
}
+ // function findTokensToRemove()
+
+ function removeAwait(
+ fixer: TSESLint.RuleFixer,
+ node: TSESTree.ReturnStatement | TSESTree.ArrowFunctionExpression,
+ ): TSESLint.RuleFix | null {
+ const awaitNode =
+ node.type === AST_NODE_TYPES.ReturnStatement
+ ? node.argument
+ : node.body;
+ // Should always be an await node; but let's be safe.
+ /* istanbul ignore if */ if (!util.isAwaitExpression(awaitNode)) {
+ return null;
+ }
+
+ const awaitToken = sourceCode.getFirstToken(
+ awaitNode,
+ util.isAwaitKeyword,
+ );
+ // Should always be the case; but let's be safe.
+ /* istanbul ignore if */ if (!awaitToken) {
+ return null;
+ }
+
+ const startAt = awaitToken.range[0];
+ let endAt = awaitToken.range[1];
+ // Also remove any extraneous whitespace after `await`, if there is any.
+ const nextToken = sourceCode.getTokenAfter(awaitToken, {
+ includeComments: true,
+ });
+ if (nextToken) {
+ endAt = nextToken.range[0];
+ }
+
+ return fixer.removeRange([startAt, endAt]);
+ }
+
+ function insertAwait(
+ fixer: TSESLint.RuleFixer,
+ node: TSESTree.ReturnStatement | TSESTree.ArrowFunctionExpression,
+ ): TSESLint.RuleFix | null {
+ const targetNode =
+ node.type === AST_NODE_TYPES.ReturnStatement
+ ? node.argument
+ : node.body;
+ // There should always be a target node; but let's be safe.
+ /* istanbul ignore if */ if (!targetNode) {
+ return null;
+ }
+
+ return fixer.insertTextBefore(targetNode, 'await ');
+ }
+
function test(
node: TSESTree.ReturnStatement | TSESTree.ArrowFunctionExpression,
expression: ts.Node,
): void {
let child: ts.Node;
- const isAwait = expression.kind === ts.SyntaxKind.AwaitExpression;
+ const isAwait = tsutils.isAwaitExpression(expression);
if (isAwait) {
child = expression.getChildAt(1);
@@ -79,6 +135,7 @@ export default util.createRule({
context.report({
messageId: 'nonPromiseAwait',
node,
+ fix: fixer => removeAwait(fixer, node),
});
return;
}
@@ -88,6 +145,7 @@ export default util.createRule({
context.report({
messageId: 'requiredPromiseAwait',
node,
+ fix: fixer => insertAwait(fixer, node),
});
}
@@ -99,6 +157,7 @@ export default util.createRule({
context.report({
messageId: 'disallowedPromiseAwait',
node,
+ fix: fixer => removeAwait(fixer, node),
});
}
@@ -111,11 +170,13 @@ export default util.createRule({
context.report({
messageId: 'disallowedPromiseAwait',
node,
+ fix: fixer => removeAwait(fixer, node),
});
} else if (!isAwait && isInTryCatch) {
context.report({
messageId: 'requiredPromiseAwait',
node,
+ fix: fixer => insertAwait(fixer, node),
});
}
diff --git a/packages/eslint-plugin/src/rules/typedef.ts b/packages/eslint-plugin/src/rules/typedef.ts
index 19c4244d9f99..dd7bcc29c61f 100644
--- a/packages/eslint-plugin/src/rules/typedef.ts
+++ b/packages/eslint-plugin/src/rules/typedef.ts
@@ -69,6 +69,31 @@ export default util.createRule<[Options], MessageIds>({
return node.type === AST_NODE_TYPES.Identifier ? node.name : undefined;
}
+ function isForOfStatementContext(
+ node: TSESTree.ArrayPattern | TSESTree.ObjectPattern,
+ ): boolean {
+ let current: TSESTree.Node | undefined = node.parent;
+ while (current) {
+ switch (current.type) {
+ case AST_NODE_TYPES.VariableDeclarator:
+ case AST_NODE_TYPES.VariableDeclaration:
+ case AST_NODE_TYPES.ObjectPattern:
+ case AST_NODE_TYPES.ArrayPattern:
+ case AST_NODE_TYPES.Property:
+ current = current.parent;
+ break;
+
+ case AST_NODE_TYPES.ForOfStatement:
+ return true;
+
+ default:
+ current = undefined;
+ }
+ }
+
+ return false;
+ }
+
function checkParameters(params: TSESTree.Parameter[]): void {
for (const param of params) {
let annotationNode: TSESTree.Node | undefined;
@@ -102,7 +127,11 @@ export default util.createRule<[Options], MessageIds>({
return {
ArrayPattern(node): void {
- if (options[OptionKeys.ArrayDestructuring] && !node.typeAnnotation) {
+ if (
+ options[OptionKeys.ArrayDestructuring] &&
+ !node.typeAnnotation &&
+ !isForOfStatementContext(node)
+ ) {
report(node);
}
},
@@ -132,7 +161,11 @@ export default util.createRule<[Options], MessageIds>({
}
},
ObjectPattern(node): void {
- if (options[OptionKeys.ObjectDestructuring] && !node.typeAnnotation) {
+ if (
+ options[OptionKeys.ObjectDestructuring] &&
+ !node.typeAnnotation &&
+ !isForOfStatementContext(node)
+ ) {
report(node);
}
},
diff --git a/packages/eslint-plugin/src/util/astUtils.ts b/packages/eslint-plugin/src/util/astUtils.ts
index 367bd93350bb..29dcdc0b459f 100644
--- a/packages/eslint-plugin/src/util/astUtils.ts
+++ b/packages/eslint-plugin/src/util/astUtils.ts
@@ -114,7 +114,27 @@ function isIdentifier(
return node?.type === AST_NODE_TYPES.Identifier;
}
+/**
+ * Checks if a node represents an `await β¦` expression.
+ */
+function isAwaitExpression(
+ node: TSESTree.Node | undefined | null,
+): node is TSESTree.AwaitExpression {
+ return node?.type === AST_NODE_TYPES.AwaitExpression;
+}
+
+/**
+ * Checks if a possible token is the `await` keyword.
+ */
+function isAwaitKeyword(
+ node: TSESTree.Token | TSESTree.Comment | undefined | null,
+): node is TSESTree.KeywordToken & { value: 'await' } {
+ return node?.type === AST_TOKEN_TYPES.Identifier && node.value === 'await';
+}
+
export {
+ isAwaitExpression,
+ isAwaitKeyword,
isConstructor,
isIdentifier,
isLogicalOrOperator,
diff --git a/packages/eslint-plugin/tests/rules/explicit-module-boundary-types.test.ts b/packages/eslint-plugin/tests/rules/explicit-module-boundary-types.test.ts
index 20a9f14a57e8..388adb994315 100644
--- a/packages/eslint-plugin/tests/rules/explicit-module-boundary-types.test.ts
+++ b/packages/eslint-plugin/tests/rules/explicit-module-boundary-types.test.ts
@@ -312,6 +312,35 @@ export class Test {
},
],
},
+ {
+ code: `
+export const Foo: FC = () => (
+ {}}
+ b={function (e) {}}
+ c={function foo(e) {}}
+ >
+
+)
+ `,
+ parserOptions: {
+ ecmaFeatures: { jsx: true },
+ },
+ },
+ {
+ code: `
+export const Foo: JSX.Element =
+ {}}
+ b={function (e) {}}
+ c={function foo(e) {}}
+ >
+
+ `,
+ parserOptions: {
+ ecmaFeatures: { jsx: true },
+ },
+ },
],
invalid: [
{
diff --git a/packages/eslint-plugin/tests/rules/no-floating-promises.test.ts b/packages/eslint-plugin/tests/rules/no-floating-promises.test.ts
index a6fcf7777542..efdbf5e1a48c 100644
--- a/packages/eslint-plugin/tests/rules/no-floating-promises.test.ts
+++ b/packages/eslint-plugin/tests/rules/no-floating-promises.test.ts
@@ -19,7 +19,9 @@ async function test() {
await Promise.resolve("value");
Promise.resolve("value").then(() => {}, () => {});
Promise.resolve("value").then(() => {}).catch(() => {});
+ Promise.resolve("value").then(() => {}).catch(() => {}).finally(() => {});
Promise.resolve("value").catch(() => {});
+ Promise.resolve("value").finally(() => {});
return Promise.resolve("value");
}
`,
@@ -36,7 +38,9 @@ async function test() {
await Promise.reject(new Error("message"));
Promise.reject(new Error("message")).then(() => {}, () => {});
Promise.reject(new Error("message")).then(() => {}).catch(() => {});
+ Promise.reject(new Error("message")).then(() => {}).catch(() => {}).finally(() => {});
Promise.reject(new Error("message")).catch(() => {});
+ Promise.reject(new Error("message")).finally(() => {});
return Promise.reject(new Error("message"));
}
`,
@@ -45,7 +49,9 @@ async function test() {
await (async () => true)();
(async () => true)().then(() => {}, () => {});
(async () => true)().then(() => {}).catch(() => {});
+ (async () => true)().then(() => {}).catch(() => {}).finally(() => {});
(async () => true)().catch(() => {});
+ (async () => true)().finally(() => {});
return (async () => true)();
}
`,
@@ -55,7 +61,9 @@ async function test() {
await returnsPromise();
returnsPromise().then(() => {}, () => {});
returnsPromise().then(() => {}).catch(() => {});
+ returnsPromise().then(() => {}).catch(() => {}).finally(() => {});
returnsPromise().catch(() => {});
+ returnsPromise().finally(() => {});
return returnsPromise();
}
`,
@@ -64,6 +72,7 @@ async function test() {
const x = Promise.resolve();
const y = x.then(() => {});
y.catch(() => {});
+ y.finally(() => {});
}
`,
`
@@ -74,6 +83,7 @@ async function test() {
`
async function test() {
Promise.resolve().catch(() => {}), 123;
+ Promise.resolve().finally(() => {}), 123;
123, Promise.resolve().then(() => {}, () => {});
123, Promise.resolve().then(() => {}, () => {}), 123;
}
@@ -95,7 +105,9 @@ async function test() {
await promiseValue;
promiseValue.then(() => {}, () => {});
promiseValue.then(() => {}).catch(() => {});
+ promiseValue.then(() => {}).catch(() => {}).finally(() => {});
promiseValue.catch(() => {});
+ promiseValue.finally(() => {});
return promiseValue;
}
`,
@@ -106,7 +118,9 @@ async function test() {
await promiseUnion;
promiseUnion.then(() => {}, () => {});
promiseUnion.then(() => {}).catch(() => {});
+ promiseUnion.then(() => {}).catch(() => {}).finally(() => {});
promiseUnion.catch(() => {});
+ promiseValue.finally(() => {});
return promiseUnion;
}
`,
@@ -117,7 +131,9 @@ async function test() {
await promiseIntersection;
promiseIntersection.then(() => {}, () => {});
promiseIntersection.then(() => {}).catch(() => {});
+ promiseIntersection.then(() => {}).catch(() => {}).finally(() => {});
promiseIntersection.catch(() => {});
+ promiseIntersection.finally(() => {});
return promiseIntersection;
}
`,
@@ -129,7 +145,9 @@ async function test() {
await canThen;
canThen.then(() => {}, () => {});
canThen.then(() => {}).catch(() => {});
+ canThen.then(() => {}).catch(() => {}).finally(() => {});
canThen.catch(() => {});
+ canThen.finally(() => {});
return canThen;
}
`,
@@ -214,7 +232,9 @@ async function test() {
await promise;
promise.then(() => {}, () => {});
promise.then(() => {}).catch(() => {});
+ promise.then(() => {}).catch(() => {}).finally(() => {});
promise.catch(() => {});
+ promise.finally(() => {});
return promise;
}
`,
@@ -227,6 +247,7 @@ async function test() {
returnsPromise()?.then(() => {}, () => {});
returnsPromise()?.then(() => {})?.catch(() => {});
returnsPromise()?.catch(() => {});
+ returnsPromise()?.finally(() => {});
return returnsPromise();
}
`,
@@ -239,6 +260,7 @@ async function test() {
Promise.resolve("value");
Promise.resolve("value").then(() => {});
Promise.resolve("value").catch();
+ Promise.resolve("value").finally();
}
`,
errors: [
@@ -254,6 +276,10 @@ async function test() {
line: 5,
messageId: 'floating',
},
+ {
+ line: 6,
+ messageId: 'floating',
+ },
],
},
{
@@ -286,6 +312,7 @@ async function test() {
Promise.reject(new Error("message"));
Promise.reject(new Error("message")).then(() => {});
Promise.reject(new Error("message")).catch();
+ Promise.reject(new Error("message")).finally();
}
`,
errors: [
@@ -301,6 +328,10 @@ async function test() {
line: 5,
messageId: 'floating',
},
+ {
+ line: 6,
+ messageId: 'floating',
+ },
],
},
{
@@ -309,6 +340,7 @@ async function test() {
(async () => true)();
(async () => true)().then(() => {});
(async () => true)().catch();
+ (async () => true)().finally();
}
`,
errors: [
@@ -324,6 +356,10 @@ async function test() {
line: 5,
messageId: 'floating',
},
+ {
+ line: 6,
+ messageId: 'floating',
+ },
],
},
{
@@ -334,6 +370,7 @@ async function test() {
returnsPromise();
returnsPromise().then(() => {});
returnsPromise().catch();
+ returnsPromise().finally();
}
`,
errors: [
@@ -349,6 +386,10 @@ async function test() {
line: 7,
messageId: 'floating',
},
+ {
+ line: 8,
+ messageId: 'floating',
+ },
],
},
{
@@ -440,6 +481,7 @@ async function test() {
promiseValue;
promiseValue.then(() => {});
promiseValue.catch();
+ promiseValue.finally();
}
`,
errors: [
@@ -455,6 +497,10 @@ async function test() {
line: 7,
messageId: 'floating',
},
+ {
+ line: 8,
+ messageId: 'floating',
+ },
],
},
{
@@ -480,6 +526,7 @@ async function test() {
promiseIntersection;
promiseIntersection.then(() => {})
promiseIntersection.catch();
+ promiseIntersection.finally();
}
`,
errors: [
@@ -495,6 +542,10 @@ async function test() {
line: 7,
messageId: 'floating',
},
+ {
+ line: 8,
+ messageId: 'floating',
+ },
],
},
{
@@ -506,6 +557,7 @@ async function test() {
canThen;
canThen.then(() => {});
canThen.catch();
+ canThen.finally();
}
`,
errors: [
@@ -521,6 +573,10 @@ async function test() {
line: 8,
messageId: 'floating',
},
+ {
+ line: 9,
+ messageId: 'floating',
+ },
],
},
{
diff --git a/packages/eslint-plugin/tests/rules/return-await.test.ts b/packages/eslint-plugin/tests/rules/return-await.test.ts
index fc5f2597ebf4..8599a937e198 100644
--- a/packages/eslint-plugin/tests/rules/return-await.test.ts
+++ b/packages/eslint-plugin/tests/rules/return-await.test.ts
@@ -164,6 +164,9 @@ ruleTester.run('return-await', rule, {
code: `async function test() {
return await 1;
}`,
+ output: `async function test() {
+ return 1;
+ }`,
errors: [
{
line: 2,
@@ -171,8 +174,52 @@ ruleTester.run('return-await', rule, {
},
],
},
+ {
+ code: `async function test() {
+ const foo = 1;
+ return await{foo};
+ }`,
+ output: `async function test() {
+ const foo = 1;
+ return {foo};
+ }`,
+ errors: [
+ {
+ line: 3,
+ messageId: 'nonPromiseAwait',
+ },
+ ],
+ },
+ {
+ code: `async function test() {
+ const foo = 1;
+ return await
+ foo;
+ }`,
+ output: `async function test() {
+ const foo = 1;
+ return foo;
+ }`,
+ errors: [
+ {
+ line: 3,
+ messageId: 'nonPromiseAwait',
+ },
+ ],
+ },
{
code: `const test = async () => await 1;`,
+ output: `const test = async () => 1;`,
+ errors: [
+ {
+ line: 1,
+ messageId: 'nonPromiseAwait',
+ },
+ ],
+ },
+ {
+ code: `const test = async () => await/* comment */1;`,
+ output: `const test = async () => /* comment */1;`,
errors: [
{
line: 1,
@@ -182,6 +229,7 @@ ruleTester.run('return-await', rule, {
},
{
code: `const test = async () => await Promise.resolve(1);`,
+ output: `const test = async () => Promise.resolve(1);`,
errors: [
{
line: 1,
@@ -199,6 +247,15 @@ ruleTester.run('return-await', rule, {
console.log('cleanup');
}
}`,
+ output: `async function test() {
+ try {
+ return await Promise.resolve(1);
+ } catch (e) {
+ return await Promise.resolve(2);
+ } finally {
+ console.log('cleanup');
+ }
+ }`,
errors: [
{
line: 3,
@@ -214,6 +271,9 @@ ruleTester.run('return-await', rule, {
code: `async function test() {
return await Promise.resolve(1);
}`,
+ output: `async function test() {
+ return Promise.resolve(1);
+ }`,
errors: [
{
line: 2,
@@ -226,6 +286,9 @@ ruleTester.run('return-await', rule, {
code: `async function test() {
return await 1;
}`,
+ output: `async function test() {
+ return 1;
+ }`,
errors: [
{
line: 2,
@@ -236,6 +299,7 @@ ruleTester.run('return-await', rule, {
{
options: ['in-try-catch'],
code: `const test = async () => await 1;`,
+ output: `const test = async () => 1;`,
errors: [
{
line: 1,
@@ -246,6 +310,7 @@ ruleTester.run('return-await', rule, {
{
options: ['in-try-catch'],
code: `const test = async () => await Promise.resolve(1);`,
+ output: `const test = async () => Promise.resolve(1);`,
errors: [
{
line: 1,
@@ -264,6 +329,15 @@ ruleTester.run('return-await', rule, {
console.log('cleanup');
}
}`,
+ output: `async function test() {
+ try {
+ return await Promise.resolve(1);
+ } catch (e) {
+ return await Promise.resolve(2);
+ } finally {
+ console.log('cleanup');
+ }
+ }`,
errors: [
{
line: 3,
@@ -280,6 +354,9 @@ ruleTester.run('return-await', rule, {
code: `async function test() {
return await Promise.resolve(1);
}`,
+ output: `async function test() {
+ return Promise.resolve(1);
+ }`,
errors: [
{
line: 2,
@@ -292,6 +369,9 @@ ruleTester.run('return-await', rule, {
code: `async function test() {
return await 1;
}`,
+ output: `async function test() {
+ return 1;
+ }`,
errors: [
{
line: 2,
@@ -310,6 +390,15 @@ ruleTester.run('return-await', rule, {
console.log('cleanup');
}
}`,
+ output: `async function test() {
+ try {
+ return Promise.resolve(1);
+ } catch (e) {
+ return Promise.resolve(2);
+ } finally {
+ console.log('cleanup');
+ }
+ }`,
errors: [
{
line: 3,
@@ -326,6 +415,9 @@ ruleTester.run('return-await', rule, {
code: `async function test() {
return await Promise.resolve(1);
}`,
+ output: `async function test() {
+ return Promise.resolve(1);
+ }`,
errors: [
{
line: 2,
@@ -338,6 +430,9 @@ ruleTester.run('return-await', rule, {
code: `async function test() {
return await 1;
}`,
+ output: `async function test() {
+ return 1;
+ }`,
errors: [
{
line: 2,
@@ -356,6 +451,15 @@ ruleTester.run('return-await', rule, {
console.log('cleanup');
}
}`,
+ output: `async function test() {
+ try {
+ return await Promise.resolve(1);
+ } catch (e) {
+ return await Promise.resolve(2);
+ } finally {
+ console.log('cleanup');
+ }
+ }`,
errors: [
{
line: 3,
@@ -372,6 +476,9 @@ ruleTester.run('return-await', rule, {
code: `async function test() {
return Promise.resolve(1);
}`,
+ output: `async function test() {
+ return await Promise.resolve(1);
+ }`,
errors: [
{
line: 2,
diff --git a/packages/eslint-plugin/tests/rules/typedef.test.ts b/packages/eslint-plugin/tests/rules/typedef.test.ts
index c9e35c356eb2..679ed1a8a519 100644
--- a/packages/eslint-plugin/tests/rules/typedef.test.ts
+++ b/packages/eslint-plugin/tests/rules/typedef.test.ts
@@ -38,6 +38,30 @@ ruleTester.run('typedef', rule, {
},
],
},
+ {
+ code: `for (const [key, val] of new Map([['key', 1]])) {}`,
+ options: [
+ {
+ arrayDestructuring: true,
+ },
+ ],
+ },
+ {
+ code: `for (const [[key]] of [[['key']]]) {}`,
+ options: [
+ {
+ arrayDestructuring: true,
+ },
+ ],
+ },
+ {
+ code: `for (const [[{ key }]] of [[[{ key: 'value' }]]]) {}`,
+ options: [
+ {
+ arrayDestructuring: true,
+ },
+ ],
+ },
`let a: number;
[a] = [1];`,
// Arrow parameters
@@ -93,6 +117,22 @@ ruleTester.run('typedef', rule, {
},
],
},
+ {
+ code: `for (const {p1: {p2: { p3 }}} of [{p1: {p2: {p3: 'value'}}}]) {}`,
+ options: [
+ {
+ objectDestructuring: true,
+ },
+ ],
+ },
+ {
+ code: `for (const {p1: {p2: { p3: [key] }}} of [{p1: {p2: {p3: ['value']}}}]) {}`,
+ options: [
+ {
+ objectDestructuring: true,
+ },
+ ],
+ },
{
code: `const { a } = { a: 1 };`,
options: [
@@ -101,6 +141,14 @@ ruleTester.run('typedef', rule, {
},
],
},
+ {
+ code: `for (const { key, val } of [{ key: 'key', val: 1 }]) {}`,
+ options: [
+ {
+ objectDestructuring: true,
+ },
+ ],
+ },
// Function parameters
`function receivesNumber(a: number): void { }`,
`function receivesStrings(a: string, b: string): void { }`,
diff --git a/packages/experimental-utils/CHANGELOG.md b/packages/experimental-utils/CHANGELOG.md
index e85cdffc4b2c..6ed1898fe0ba 100644
--- a/packages/experimental-utils/CHANGELOG.md
+++ b/packages/experimental-utils/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+# [2.21.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.20.0...v2.21.0) (2020-02-24)
+
+**Note:** Version bump only for package @typescript-eslint/experimental-utils
+
+
+
+
+
# [2.20.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.19.2...v2.20.0) (2020-02-17)
**Note:** Version bump only for package @typescript-eslint/experimental-utils
diff --git a/packages/experimental-utils/package.json b/packages/experimental-utils/package.json
index 31eccbf1f64f..927154687061 100644
--- a/packages/experimental-utils/package.json
+++ b/packages/experimental-utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@typescript-eslint/experimental-utils",
- "version": "2.20.0",
+ "version": "2.21.0",
"description": "(Experimental) Utilities for working with TypeScript + ESLint together",
"keywords": [
"eslint",
@@ -37,7 +37,7 @@
},
"dependencies": {
"@types/json-schema": "^7.0.3",
- "@typescript-eslint/typescript-estree": "2.20.0",
+ "@typescript-eslint/typescript-estree": "2.21.0",
"eslint-scope": "^5.0.0"
},
"peerDependencies": {
diff --git a/packages/parser/CHANGELOG.md b/packages/parser/CHANGELOG.md
index 0a89b836d18a..039e2d78eda6 100644
--- a/packages/parser/CHANGELOG.md
+++ b/packages/parser/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+# [2.21.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.20.0...v2.21.0) (2020-02-24)
+
+**Note:** Version bump only for package @typescript-eslint/parser
+
+
+
+
+
# [2.20.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.19.2...v2.20.0) (2020-02-17)
**Note:** Version bump only for package @typescript-eslint/parser
diff --git a/packages/parser/package.json b/packages/parser/package.json
index 17ac2bae6c0e..13918ec8784d 100644
--- a/packages/parser/package.json
+++ b/packages/parser/package.json
@@ -1,6 +1,6 @@
{
"name": "@typescript-eslint/parser",
- "version": "2.20.0",
+ "version": "2.21.0",
"description": "An ESLint custom parser which leverages TypeScript ESTree",
"main": "dist/parser.js",
"types": "dist/parser.d.ts",
@@ -43,13 +43,13 @@
},
"dependencies": {
"@types/eslint-visitor-keys": "^1.0.0",
- "@typescript-eslint/experimental-utils": "2.20.0",
- "@typescript-eslint/typescript-estree": "2.20.0",
+ "@typescript-eslint/experimental-utils": "2.21.0",
+ "@typescript-eslint/typescript-estree": "2.21.0",
"eslint-visitor-keys": "^1.1.0"
},
"devDependencies": {
"@types/glob": "^7.1.1",
- "@typescript-eslint/shared-fixtures": "2.20.0",
+ "@typescript-eslint/shared-fixtures": "2.21.0",
"glob": "*"
},
"peerDependenciesMeta": {
diff --git a/packages/shared-fixtures/CHANGELOG.md b/packages/shared-fixtures/CHANGELOG.md
index 4bc15b28871c..5eef3db60f0f 100644
--- a/packages/shared-fixtures/CHANGELOG.md
+++ b/packages/shared-fixtures/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+# [2.21.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.20.0...v2.21.0) (2020-02-24)
+
+**Note:** Version bump only for package @typescript-eslint/shared-fixtures
+
+
+
+
+
# [2.20.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.19.2...v2.20.0) (2020-02-17)
**Note:** Version bump only for package @typescript-eslint/shared-fixtures
diff --git a/packages/shared-fixtures/package.json b/packages/shared-fixtures/package.json
index f955ffcc367f..8b9f8ebf381d 100644
--- a/packages/shared-fixtures/package.json
+++ b/packages/shared-fixtures/package.json
@@ -1,6 +1,6 @@
{
"name": "@typescript-eslint/shared-fixtures",
- "version": "2.20.0",
+ "version": "2.21.0",
"private": true,
"scripts": {
"build": "tsc -b tsconfig.build.json",
diff --git a/packages/typescript-estree/CHANGELOG.md b/packages/typescript-estree/CHANGELOG.md
index bcd32357a487..681a0d9a72a3 100644
--- a/packages/typescript-estree/CHANGELOG.md
+++ b/packages/typescript-estree/CHANGELOG.md
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+# [2.21.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.20.0...v2.21.0) (2020-02-24)
+
+
+### Bug Fixes
+
+* **typescript-estree:** process.stdout can be undefined ([#1619](https://github.com/typescript-eslint/typescript-eslint/issues/1619)) ([0d8e87e](https://github.com/typescript-eslint/typescript-eslint/commit/0d8e87e09704588273bc94a740279b3e8af7474f))
+
+
+
+
+
# [2.20.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.19.2...v2.20.0) (2020-02-17)
**Note:** Version bump only for package @typescript-eslint/typescript-estree
diff --git a/packages/typescript-estree/package.json b/packages/typescript-estree/package.json
index 894aa7565a21..a9697fc59cad 100644
--- a/packages/typescript-estree/package.json
+++ b/packages/typescript-estree/package.json
@@ -1,6 +1,6 @@
{
"name": "@typescript-eslint/typescript-estree",
- "version": "2.20.0",
+ "version": "2.21.0",
"description": "A parser that converts TypeScript source code into an ESTree compatible form",
"main": "dist/parser.js",
"types": "dist/parser.d.ts",
@@ -58,7 +58,7 @@
"@types/lodash": "^4.14.149",
"@types/semver": "^6.2.0",
"@types/tmp": "^0.1.0",
- "@typescript-eslint/shared-fixtures": "2.20.0",
+ "@typescript-eslint/shared-fixtures": "2.21.0",
"tmp": "^0.1.0",
"typescript": "*"
},
diff --git a/packages/typescript-estree/src/parser.ts b/packages/typescript-estree/src/parser.ts
index 6142efaf1af2..b5e75d155595 100644
--- a/packages/typescript-estree/src/parser.ts
+++ b/packages/typescript-estree/src/parser.ts
@@ -261,7 +261,7 @@ function applyParserOptionsToExtra(options: TSESTreeOptions): void {
function warnAboutTSVersion(): void {
if (!isRunningSupportedTypeScriptVersion && !warnedAboutTSVersion) {
- const isTTY = typeof process === undefined ? false : process.stdout.isTTY;
+ const isTTY = typeof process === undefined ? false : process.stdout?.isTTY;
if (isTTY) {
const border = '=============';
const versionWarning = [