Skip to content

Commit

Permalink
fix(eslint-plugin): [no-throw-literal] false positive with logical ex…
Browse files Browse the repository at this point in the history
…pressions (#2645)
  • Loading branch information
jsone-studios committed Oct 11, 2020
1 parent 8e44c78 commit 57aa6c7
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 60 deletions.
60 changes: 13 additions & 47 deletions packages/eslint-plugin/src/rules/no-throw-literal.ts
Expand Up @@ -61,40 +61,6 @@ export default util.createRule({
return false;
}

function tryGetThrowArgumentType(node: TSESTree.Node): ts.Type | null {
switch (node.type) {
case AST_NODE_TYPES.Identifier:
case AST_NODE_TYPES.CallExpression:
case AST_NODE_TYPES.NewExpression:
case AST_NODE_TYPES.MemberExpression:
case AST_NODE_TYPES.TSAsExpression: {
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node);
return checker.getTypeAtLocation(tsNode);
}

case AST_NODE_TYPES.AssignmentExpression:
return tryGetThrowArgumentType(node.right);

case AST_NODE_TYPES.SequenceExpression:
return tryGetThrowArgumentType(
node.expressions[node.expressions.length - 1],
);

case AST_NODE_TYPES.LogicalExpression: {
const left = tryGetThrowArgumentType(node.left);
return left ?? tryGetThrowArgumentType(node.right);
}

case AST_NODE_TYPES.ConditionalExpression: {
const consequent = tryGetThrowArgumentType(node.consequent);
return consequent ?? tryGetThrowArgumentType(node.alternate);
}

default:
return null;
}
}

function checkThrowArgument(node: TSESTree.Node): void {
if (
node.type === AST_NODE_TYPES.AwaitExpression ||
Expand All @@ -103,20 +69,20 @@ export default util.createRule({
return;
}

const type = tryGetThrowArgumentType(node);
if (type) {
if (type.flags & ts.TypeFlags.Undefined) {
context.report({ node, messageId: 'undef' });
return;
}
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node);
const type = checker.getTypeAtLocation(tsNode);

if (
util.isTypeAnyType(type) ||
util.isTypeUnknownType(type) ||
isErrorLike(type)
) {
return;
}
if (type.flags & ts.TypeFlags.Undefined) {
context.report({ node, messageId: 'undef' });
return;
}

if (
util.isTypeAnyType(type) ||
util.isTypeUnknownType(type) ||
isErrorLike(type)
) {
return;
}

context.report({ node, messageId: 'object' });
Expand Down
49 changes: 36 additions & 13 deletions packages/eslint-plugin/tests/rules/no-throw-literal.test.ts
Expand Up @@ -61,14 +61,13 @@ throw new CustomError();
`
class CustomError1 extends Error {}
class CustomError2 extends CustomError1 {}
throw new CustomError();
throw new CustomError2();
`,
'throw (foo = new Error());',
'throw (1, 2, new Error());',
"throw 'literal' && new Error();",
"throw new Error() || 'literal';",
"throw foo ? new Error() : 'literal';",
"throw foo ? 'literal' : new Error();",
'throw foo ? new Error() : new Error();',
`
function* foo() {
let index = 0;
Expand Down Expand Up @@ -112,6 +111,18 @@ declare const foo: Error | string;
throw foo as Error;
`,
'throw new Error() as Error;',
`
declare const nullishError: Error | undefined;
throw nullishError ?? new Error();
`,
`
declare const nullishError: Error | undefined;
throw nullishError || new Error();
`,
`
declare const nullishError: Error | undefined;
throw nullishError ? nullishError : new Error();
`,
],
invalid: [
{
Expand Down Expand Up @@ -207,19 +218,31 @@ throw a + 'b';
},
{
code: "throw 'literal' && 'not an Error';",
errors: [
{
messageId: 'object',
},
],
errors: [{ messageId: 'object' }],
},
{
code: "throw 'literal' || new Error();",
errors: [{ messageId: 'object' }],
},
{
code: "throw new Error() && 'literal';",
errors: [{ messageId: 'object' }],
},
{
code: "throw 'literal' ?? new Error();",
errors: [{ messageId: 'object' }],
},
{
code: "throw foo ? 'not an Error' : 'literal';",
errors: [
{
messageId: 'object',
},
],
errors: [{ messageId: 'object' }],
},
{
code: "throw foo ? new Error() : 'literal';",
errors: [{ messageId: 'object' }],
},
{
code: "throw foo ? 'literal' : new Error();",
errors: [{ messageId: 'object' }],
},
{
code: 'throw `${err}`;',
Expand Down

0 comments on commit 57aa6c7

Please sign in to comment.