From fa169e79661821f0e0e64a56d6db9da42c3c8654 Mon Sep 17 00:00:00 2001 From: Soobin Bak Date: Mon, 3 Aug 2020 05:37:07 +0900 Subject: [PATCH] fix(eslint-plugin): [no-implied-eval] don't report when `Function` is imported (#2348) --- .../src/rules/no-implied-eval.ts | 20 +++++++++++++++++-- .../eslint-plugin/tests/fixtures/class.ts | 3 +++ .../tests/rules/no-implied-eval.test.ts | 5 +++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-implied-eval.ts b/packages/eslint-plugin/src/rules/no-implied-eval.ts index dd36fb73ec4..afda630b6b6 100644 --- a/packages/eslint-plugin/src/rules/no-implied-eval.ts +++ b/packages/eslint-plugin/src/rules/no-implied-eval.ts @@ -35,6 +35,7 @@ export default util.createRule({ defaultOptions: [], create(context) { const parserServices = util.getParserServices(context); + const program = parserServices.program; const checker = parserServices.program.getTypeChecker(); function getCalleeName( @@ -113,14 +114,29 @@ export default util.createRule({ function checkImpliedEval( node: TSESTree.NewExpression | TSESTree.CallExpression, ): void { + const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node.callee); + const type = checker.getTypeAtLocation(tsNode); + const calleeName = getCalleeName(node.callee); if (calleeName === null) { return; } if (calleeName === FUNCTION_CONSTRUCTOR) { - context.report({ node, messageId: 'noFunctionConstructor' }); - return; + const symbol = type.getSymbol(); + if (symbol) { + const declarations = symbol.getDeclarations() ?? []; + for (const declaration of declarations) { + const sourceFile = declaration.getSourceFile(); + if (program.isSourceFileDefaultLibrary(sourceFile)) { + context.report({ node, messageId: 'noFunctionConstructor' }); + return; + } + } + } else { + context.report({ node, messageId: 'noFunctionConstructor' }); + return; + } } if (node.arguments.length === 0) { diff --git a/packages/eslint-plugin/tests/fixtures/class.ts b/packages/eslint-plugin/tests/fixtures/class.ts index 044e44e44ae..89f06af9e8e 100644 --- a/packages/eslint-plugin/tests/fixtures/class.ts +++ b/packages/eslint-plugin/tests/fixtures/class.ts @@ -8,3 +8,6 @@ export const console = { log() {} }; export class Reducable { reduce() {} } + +// used by no-implied-eval test function imports +export class Function {} diff --git a/packages/eslint-plugin/tests/rules/no-implied-eval.test.ts b/packages/eslint-plugin/tests/rules/no-implied-eval.test.ts index 818514c6b0b..f5ceba4fe94 100644 --- a/packages/eslint-plugin/tests/rules/no-implied-eval.test.ts +++ b/packages/eslint-plugin/tests/rules/no-implied-eval.test.ts @@ -6,6 +6,7 @@ const ruleTester = new RuleTester({ parserOptions: { tsconfigRootDir: rootDir, ecmaVersion: 2015, + sourceType: 'module', project: './tsconfig.json', }, parser: '@typescript-eslint/parser', @@ -241,6 +242,10 @@ const fn = (foo: () => void) => { execScript(foo); }; `, + ` +import { Function } from './class'; +new Function('foo'); + `, ], invalid: [