From e112028a1de76c3c8b29e6f7e74d5a3e6af2b9fe Mon Sep 17 00:00:00 2001 From: fraxken Date: Fri, 22 Dec 2023 18:55:48 +0100 Subject: [PATCH] feat(getCallExpressionIdentifier): add resolveCallExpression option --- .../src/getCallExpressionIdentifier.js | 14 +++++-- workspaces/estree-ast-utils/src/index.d.ts | 2 +- .../test/getCallExpressionIdentifier.spec.js | 38 ++++++++++++++++++- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/workspaces/estree-ast-utils/src/getCallExpressionIdentifier.js b/workspaces/estree-ast-utils/src/getCallExpressionIdentifier.js index 1f9f80c..7e3c059 100644 --- a/workspaces/estree-ast-utils/src/getCallExpressionIdentifier.js +++ b/workspaces/estree-ast-utils/src/getCallExpressionIdentifier.js @@ -1,21 +1,29 @@ // Import Internal Dependencies import { getMemberExpressionIdentifier } from "./getMemberExpressionIdentifier.js"; +import { VariableTracer } from "./utils/VariableTracer.js"; /** * @param {any} node + * @param {object} options + * @param {VariableTracer} [options.tracer=null] + * @param {boolean} [options.resolveCallExpression=true] * @returns {string | null} */ -export function getCallExpressionIdentifier(node) { +export function getCallExpressionIdentifier(node, options = {}) { if (node.type !== "CallExpression") { return null; } + const { tracer = null, resolveCallExpression = true } = options; if (node.callee.type === "Identifier") { return node.callee.name; } if (node.callee.type === "MemberExpression") { - return [...getMemberExpressionIdentifier(node.callee)].join("."); + return [ + ...getMemberExpressionIdentifier(node.callee, { tracer }) + ].join("."); } - return getCallExpressionIdentifier(node.callee); + return resolveCallExpression ? + getCallExpressionIdentifier(node.callee, { tracer }) : null; } diff --git a/workspaces/estree-ast-utils/src/index.d.ts b/workspaces/estree-ast-utils/src/index.d.ts index d888508..b62799a 100644 --- a/workspaces/estree-ast-utils/src/index.d.ts +++ b/workspaces/estree-ast-utils/src/index.d.ts @@ -16,7 +16,7 @@ export function getCallExpressionArguments( ): string[] | null; export function getCallExpressionIdentifier( - node: any + node: any, options?: { tracer?: VariableTracer, resolveCallExpression?: boolean } ): string | null; export function getMemberExpressionIdentifier( diff --git a/workspaces/estree-ast-utils/test/getCallExpressionIdentifier.spec.js b/workspaces/estree-ast-utils/test/getCallExpressionIdentifier.spec.js index e0d29ec..67778f0 100644 --- a/workspaces/estree-ast-utils/test/getCallExpressionIdentifier.spec.js +++ b/workspaces/estree-ast-utils/test/getCallExpressionIdentifier.spec.js @@ -13,7 +13,7 @@ test("given a JavaScript eval CallExpression then it must return eval", (tape) = tape.end(); }); -test("given a JavaScript Function() CallExpression then it must return Function", (tape) => { +test("given a Function(`...`)() Double CallExpression then it must return the Function literal identifier", (tape) => { const [astNode] = codeToAst("Function(\"return this\")();"); const nodeIdentifier = getCallExpressionIdentifier(getExpressionFromStatement(astNode)); @@ -21,6 +21,18 @@ test("given a JavaScript Function() CallExpression then it must return Function" tape.end(); }); +test(`given a Function("...")() Double CallExpression with resolveCallExpression options disabled +then it must return null`, (tape) => { + const [astNode] = codeToAst("Function(\"return this\")();"); + const nodeIdentifier = getCallExpressionIdentifier( + getExpressionFromStatement(astNode), + { resolveCallExpression: false } + ); + + tape.strictEqual(nodeIdentifier, null); + tape.end(); +}); + test("given a JavaScript AssignmentExpression then it must return null", (tape) => { const [astNode] = codeToAst("foo = 10;"); const nodeIdentifier = getCallExpressionIdentifier(getExpressionFromStatement(astNode)); @@ -28,3 +40,27 @@ test("given a JavaScript AssignmentExpression then it must return null", (tape) tape.strictEqual(nodeIdentifier, null); tape.end(); }); + +test(`given a require statement immediatly invoked with resolveCallExpression options enabled +then it must return require literal identifier`, (tape) => { + const [astNode] = codeToAst("require('foo')();"); + const nodeIdentifier = getCallExpressionIdentifier( + getExpressionFromStatement(astNode), + { resolveCallExpression: true } + ); + + tape.strictEqual(nodeIdentifier, "require"); + tape.end(); +}); + +test(`given a require statement immediatly invoked with resolveCallExpression options disabled +then it must return null`, (tape) => { + const [astNode] = codeToAst("require('foo')();"); + const nodeIdentifier = getCallExpressionIdentifier( + getExpressionFromStatement(astNode), + { resolveCallExpression: false } + ); + + tape.strictEqual(nodeIdentifier, null); + tape.end(); +});