From 9d4f6c7c332f0adc1898483081234f2aaf29b9a3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 18 Jul 2026 07:20:18 +0000 Subject: [PATCH 1/2] Initial plan From eccda9c9f4253c3b6ff779ad7592a7cbaeaa446e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 18 Jul 2026 07:41:14 +0000 Subject: [PATCH 2/2] feat: extract shared core-method-resolve helper and extend setOutput/exportVariable rules to detect aliased and destructured core bindings - Add core-method-resolve.ts with isCoreAliasIdentifier and isDestructuredCoreMethodIdentifier shared helpers - Update no-core-setoutput-non-string to detect const c = core; c.setOutput(...) and const { setOutput } = core; setOutput(...) - Update no-core-exportvariable-non-string similarly - Refactor require-return-after-core-setfailed to use shared helpers (no behavior change) - Add 14 new tests (7 per rule) covering aliased/destructured valid and invalid cases Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/agentic-auto-upgrade.yml | 2 +- .../src/rules/core-method-resolve.ts | 59 +++++++++++++ .../no-core-exportvariable-non-string.test.ts | 83 +++++++++++++++++++ .../no-core-exportvariable-non-string.ts | 26 +++--- .../no-core-setoutput-non-string.test.ts | 83 +++++++++++++++++++ .../src/rules/no-core-setoutput-non-string.ts | 26 +++--- .../require-return-after-core-setfailed.ts | 64 +------------- 7 files changed, 262 insertions(+), 81 deletions(-) create mode 100644 eslint-factory/src/rules/core-method-resolve.ts diff --git a/.github/workflows/agentic-auto-upgrade.yml b/.github/workflows/agentic-auto-upgrade.yml index e169cea32b6..7035101ee35 100644 --- a/.github/workflows/agentic-auto-upgrade.yml +++ b/.github/workflows/agentic-auto-upgrade.yml @@ -34,7 +34,7 @@ name: Agentic Auto-Upgrade on: schedule: - - cron: "11 4 * * 6" # Weekly (auto-upgrade) + - cron: "21 3 * * 5" # Weekly (auto-upgrade) workflow_dispatch: permissions: diff --git a/eslint-factory/src/rules/core-method-resolve.ts b/eslint-factory/src/rules/core-method-resolve.ts new file mode 100644 index 00000000000..e038867fed3 --- /dev/null +++ b/eslint-factory/src/rules/core-method-resolve.ts @@ -0,0 +1,59 @@ +import { AST_NODE_TYPES, TSESLint, TSESTree } from "@typescript-eslint/utils"; +import { CORE_ALIASES } from "./core-aliases"; + +/** + * Checks whether an Identifier is a single-assignment alias for a core-like + * object (e.g., `const c = core`). Re-assigned let bindings are rejected. + * Local shadows (e.g., a parameter also named `c`) are excluded because they + * are found first in the scope chain and their definition type will not match. + */ +export function isCoreAliasIdentifier(identifier: TSESTree.Identifier, sourceCode: TSESLint.SourceCode): boolean { + let currentScope: TSESLint.Scope.Scope | null = sourceCode.getScope(identifier); + while (currentScope !== null) { + const variable = currentScope.set.get(identifier.name); + if (variable !== undefined) { + if (variable.defs.length !== 1) return false; + const def = variable.defs[0]; + if (def.type !== "Variable") return false; + if (variable.references.some(ref => ref.isWrite() && !ref.init)) return false; + const declarator = def.node as TSESTree.VariableDeclarator; + if (!declarator.init) return false; + return declarator.id.type === AST_NODE_TYPES.Identifier && declarator.init.type === AST_NODE_TYPES.Identifier && CORE_ALIASES.has(declarator.init.name); + } + currentScope = currentScope.upper; + } + return false; +} + +/** + * Checks whether an Identifier is a destructured binding for a specific + * @actions/core method from a core-like object (e.g., `const { setOutput } = core` + * or `const { setOutput: alias } = core` where `alias` is the identifier). + * Re-assigned let bindings are rejected. Local `function setOutput()` or + * parameter shadows are excluded via the `def.type !== "Variable"` guard. + */ +export function isDestructuredCoreMethodIdentifier(identifier: TSESTree.Identifier, methodName: string, sourceCode: TSESLint.SourceCode): boolean { + let currentScope: TSESLint.Scope.Scope | null = sourceCode.getScope(identifier); + while (currentScope !== null) { + const variable = currentScope.set.get(identifier.name); + if (variable !== undefined) { + if (variable.defs.length !== 1) return false; + const def = variable.defs[0]; + if (def.type !== "Variable") return false; + if (variable.references.some(ref => ref.isWrite() && !ref.init)) return false; + const declarator = def.node as TSESTree.VariableDeclarator; + if (!declarator.init) return false; + if (declarator.id.type === AST_NODE_TYPES.ObjectPattern && declarator.init.type === AST_NODE_TYPES.Identifier && CORE_ALIASES.has(declarator.init.name)) { + return declarator.id.properties.some(prop => { + if (prop.type !== AST_NODE_TYPES.Property || prop.computed) return false; + const keyIsMethod = prop.key.type === AST_NODE_TYPES.Identifier && prop.key.name === methodName; + const valueIsAlias = prop.value.type === AST_NODE_TYPES.Identifier && prop.value.name === identifier.name; + return keyIsMethod && valueIsAlias; + }); + } + return false; + } + currentScope = currentScope.upper; + } + return false; +} diff --git a/eslint-factory/src/rules/no-core-exportvariable-non-string.test.ts b/eslint-factory/src/rules/no-core-exportvariable-non-string.test.ts index dd922b241d2..7456e9128d4 100644 --- a/eslint-factory/src/rules/no-core-exportvariable-non-string.test.ts +++ b/eslint-factory/src/rules/no-core-exportvariable-non-string.test.ts @@ -229,4 +229,87 @@ describe("no-core-exportvariable-non-string", () => { ], }); }); + + it("valid: single-assignment const alias with string value is accepted", () => { + cjsRuleTester.run("no-core-exportvariable-non-string", noCoreExportVariableNonStringRule, { + valid: [`const c = core; c.exportVariable("MY_VAR", "hello");`, `const c = core; c.exportVariable("MY_VAR", someVariable);`, `const c = coreObj; c.exportVariable("MY_VAR", "hello");`], + invalid: [], + }); + }); + + it("invalid: single-assignment const alias with non-string value is flagged", () => { + cjsRuleTester.run("no-core-exportvariable-non-string", noCoreExportVariableNonStringRule, { + valid: [], + invalid: [ + { + code: `const c = core; c.exportVariable("MY_COUNT", items.length);`, + errors: [{ messageId: "nonStringValue", suggestions: [{ messageId: "wrapWithString", output: `const c = core; c.exportVariable("MY_COUNT", String(items.length));` }] }], + }, + { + code: `const c = core; c.exportVariable("READY", true);`, + errors: [{ messageId: "nonStringValue", suggestions: [{ messageId: "wrapWithString", output: `const c = core; c.exportVariable("READY", String(true));` }] }], + }, + { + code: `const c = core; c.exportVariable("MY_VAR", null);`, + errors: [ + { + messageId: "nonStringValue", + suggestions: [ + { messageId: "useEmptyString", output: `const c = core; c.exportVariable("MY_VAR", "");` }, + { messageId: "wrapWithString", output: `const c = core; c.exportVariable("MY_VAR", String(null));` }, + ], + }, + ], + }, + ], + }); + }); + + it("valid: let alias with reassignment is NOT flagged (not a safe const alias)", () => { + cjsRuleTester.run("no-core-exportvariable-non-string", noCoreExportVariableNonStringRule, { + valid: [`let c = core; c = other; c.exportVariable("MY_VAR", 1);`], + invalid: [], + }); + }); + + it("valid: non-core const alias is NOT flagged", () => { + cjsRuleTester.run("no-core-exportvariable-non-string", noCoreExportVariableNonStringRule, { + valid: [`const c = other; c.exportVariable("MY_VAR", 1);`], + invalid: [], + }); + }); + + it("valid: destructured exportVariable from core with string value is accepted", () => { + cjsRuleTester.run("no-core-exportvariable-non-string", noCoreExportVariableNonStringRule, { + valid: [`const { exportVariable } = core; exportVariable("MY_VAR", "hello");`, `const { exportVariable } = core; exportVariable("MY_VAR", someVariable);`, `const { exportVariable: ev } = core; ev("MY_VAR", "hello");`], + invalid: [], + }); + }); + + it("invalid: destructured exportVariable from core with non-string value is flagged", () => { + cjsRuleTester.run("no-core-exportvariable-non-string", noCoreExportVariableNonStringRule, { + valid: [], + invalid: [ + { + code: `const { exportVariable } = core; exportVariable("MY_COUNT", items.length);`, + errors: [{ messageId: "nonStringValue", suggestions: [{ messageId: "wrapWithString", output: `const { exportVariable } = core; exportVariable("MY_COUNT", String(items.length));` }] }], + }, + { + code: `const { exportVariable } = core; exportVariable("READY", true);`, + errors: [{ messageId: "nonStringValue", suggestions: [{ messageId: "wrapWithString", output: `const { exportVariable } = core; exportVariable("READY", String(true));` }] }], + }, + { + code: `const { exportVariable: ev } = core; ev("MY_COUNT", items.length);`, + errors: [{ messageId: "nonStringValue", suggestions: [{ messageId: "wrapWithString", output: `const { exportVariable: ev } = core; ev("MY_COUNT", String(items.length));` }] }], + }, + ], + }); + }); + + it("valid: standalone exportVariable identifier from non-core source is NOT flagged", () => { + cjsRuleTester.run("no-core-exportvariable-non-string", noCoreExportVariableNonStringRule, { + valid: [`function exportVariable(k, v) {} exportVariable("MY_VAR", 1);`, `const { exportVariable } = other; exportVariable("MY_VAR", 1);`], + invalid: [], + }); + }); }); diff --git a/eslint-factory/src/rules/no-core-exportvariable-non-string.ts b/eslint-factory/src/rules/no-core-exportvariable-non-string.ts index 620c56f527a..7c13654669b 100644 --- a/eslint-factory/src/rules/no-core-exportvariable-non-string.ts +++ b/eslint-factory/src/rules/no-core-exportvariable-non-string.ts @@ -1,5 +1,6 @@ import { AST_NODE_TYPES, ESLintUtils, TSESLint } from "@typescript-eslint/utils"; import { CORE_ALIASES } from "./core-aliases"; +import { isCoreAliasIdentifier, isDestructuredCoreMethodIdentifier } from "./core-method-resolve"; import { nonStringKind, NULL_KIND, UNDEFINED_KIND } from "./non-string-kind"; const createRule = ESLintUtils.RuleCreator(name => `https://github.com/github/gh-aw/tree/main/eslint-factory#${name}`); @@ -11,7 +12,7 @@ export const noCoreExportVariableNonStringRule = createRule({ hasSuggestions: true, docs: { description: - "Require core.exportVariable value arguments to be explicit strings; passing numbers, booleans, null, undefined, or .length can silently produce unexpected string representations (e.g. 'null', 'true') in downstream GitHub Actions steps that read the exported environment variable. Detects only calls in the form core.exportVariable(name, value).", + "Require core.exportVariable value arguments to be explicit strings; passing numbers, booleans, null, undefined, or .length can silently produce unexpected string representations (e.g. 'null', 'true') in downstream GitHub Actions steps that read the exported environment variable. Detects calls in the form core.exportVariable(name, value), aliased (const c = core; c.exportVariable(...)), and destructured (const { exportVariable } = core; exportVariable(...)).", }, schema: [], messages: { @@ -29,16 +30,21 @@ export const noCoreExportVariableNonStringRule = createRule({ CallExpression(node) { const callee = node.callee; - // Must be a member expression: something.exportVariable(...) - if (callee.type !== AST_NODE_TYPES.MemberExpression) return; + if (callee.type === AST_NODE_TYPES.MemberExpression) { + // Object must be a known @actions/core alias or a single-assignment alias (e.g. `const c = core`) + if (callee.object.type !== AST_NODE_TYPES.Identifier) return; + if (!CORE_ALIASES.has(callee.object.name) && !isCoreAliasIdentifier(callee.object, sourceCode)) return; - // Object must be a known @actions/core alias (`core` or `coreObj`) - if (callee.object.type !== AST_NODE_TYPES.Identifier || !CORE_ALIASES.has(callee.object.name)) return; - - // Property must be `exportVariable` (direct or computed string-literal access) - const prop = callee.property; - const isExportVariableProp = (!callee.computed && prop.type === AST_NODE_TYPES.Identifier && prop.name === "exportVariable") || (callee.computed && prop.type === AST_NODE_TYPES.Literal && prop.value === "exportVariable"); - if (!isExportVariableProp) return; + // Property must be `exportVariable` (direct or computed string-literal access) + const prop = callee.property; + const isExportVariableProp = (!callee.computed && prop.type === AST_NODE_TYPES.Identifier && prop.name === "exportVariable") || (callee.computed && prop.type === AST_NODE_TYPES.Literal && prop.value === "exportVariable"); + if (!isExportVariableProp) return; + } else if (callee.type === AST_NODE_TYPES.Identifier) { + // Destructured: `const { exportVariable } = core; exportVariable(...)` or `const { exportVariable: alias } = core; alias(...)` + if (!isDestructuredCoreMethodIdentifier(callee, "exportVariable", sourceCode)) return; + } else { + return; + } // core.exportVariable expects exactly two arguments: (name, value) if (node.arguments.length !== 2) return; diff --git a/eslint-factory/src/rules/no-core-setoutput-non-string.test.ts b/eslint-factory/src/rules/no-core-setoutput-non-string.test.ts index 1b9d3f8d5e7..92aa8c2d0b0 100644 --- a/eslint-factory/src/rules/no-core-setoutput-non-string.test.ts +++ b/eslint-factory/src/rules/no-core-setoutput-non-string.test.ts @@ -247,4 +247,87 @@ describe("no-core-setoutput-non-string", () => { ], }); }); + + it("valid: single-assignment const alias with string value is accepted", () => { + cjsRuleTester.run("no-core-setoutput-non-string", noCoreSetOutputNonStringRule, { + valid: [`const c = core; c.setOutput("n", "str");`, `const c = core; c.setOutput("n", someVariable);`, `const c = coreObj; c.setOutput("n", "str");`], + invalid: [], + }); + }); + + it("invalid: single-assignment const alias with non-string value is flagged", () => { + cjsRuleTester.run("no-core-setoutput-non-string", noCoreSetOutputNonStringRule, { + valid: [], + invalid: [ + { + code: `const c = core; c.setOutput("count", items.length);`, + errors: [{ messageId: "nonStringValue", suggestions: [{ messageId: "wrapWithString", output: `const c = core; c.setOutput("count", String(items.length));` }] }], + }, + { + code: `const c = core; c.setOutput("flag", true);`, + errors: [{ messageId: "nonStringValue", suggestions: [{ messageId: "wrapWithString", output: `const c = core; c.setOutput("flag", String(true));` }] }], + }, + { + code: `const c = core; c.setOutput("result", null);`, + errors: [ + { + messageId: "nonStringValue", + suggestions: [ + { messageId: "useEmptyString", output: `const c = core; c.setOutput("result", "");` }, + { messageId: "wrapWithString", output: `const c = core; c.setOutput("result", String(null));` }, + ], + }, + ], + }, + ], + }); + }); + + it("valid: let alias with reassignment is NOT flagged (not a safe const alias)", () => { + cjsRuleTester.run("no-core-setoutput-non-string", noCoreSetOutputNonStringRule, { + valid: [`let c = core; c = other; c.setOutput("n", 1);`], + invalid: [], + }); + }); + + it("valid: non-core const alias is NOT flagged", () => { + cjsRuleTester.run("no-core-setoutput-non-string", noCoreSetOutputNonStringRule, { + valid: [`const c = other; c.setOutput("n", 1);`], + invalid: [], + }); + }); + + it("valid: destructured setOutput from core with string value is accepted", () => { + cjsRuleTester.run("no-core-setoutput-non-string", noCoreSetOutputNonStringRule, { + valid: [`const { setOutput } = core; setOutput("n", "str");`, `const { setOutput } = core; setOutput("n", someVariable);`, `const { setOutput: so } = core; so("n", "str");`], + invalid: [], + }); + }); + + it("invalid: destructured setOutput from core with non-string value is flagged", () => { + cjsRuleTester.run("no-core-setoutput-non-string", noCoreSetOutputNonStringRule, { + valid: [], + invalid: [ + { + code: `const { setOutput } = core; setOutput("count", items.length);`, + errors: [{ messageId: "nonStringValue", suggestions: [{ messageId: "wrapWithString", output: `const { setOutput } = core; setOutput("count", String(items.length));` }] }], + }, + { + code: `const { setOutput } = core; setOutput("flag", true);`, + errors: [{ messageId: "nonStringValue", suggestions: [{ messageId: "wrapWithString", output: `const { setOutput } = core; setOutput("flag", String(true));` }] }], + }, + { + code: `const { setOutput: so } = core; so("n", items.length);`, + errors: [{ messageId: "nonStringValue", suggestions: [{ messageId: "wrapWithString", output: `const { setOutput: so } = core; so("n", String(items.length));` }] }], + }, + ], + }); + }); + + it("valid: standalone setOutput identifier from non-core source is NOT flagged", () => { + cjsRuleTester.run("no-core-setoutput-non-string", noCoreSetOutputNonStringRule, { + valid: [`function setOutput(k, v) {} setOutput("n", 1);`, `const { setOutput } = other; setOutput("n", 1);`], + invalid: [], + }); + }); }); diff --git a/eslint-factory/src/rules/no-core-setoutput-non-string.ts b/eslint-factory/src/rules/no-core-setoutput-non-string.ts index 1bb0d03bf78..034684c7de6 100644 --- a/eslint-factory/src/rules/no-core-setoutput-non-string.ts +++ b/eslint-factory/src/rules/no-core-setoutput-non-string.ts @@ -1,5 +1,6 @@ import { AST_NODE_TYPES, ESLintUtils, TSESLint } from "@typescript-eslint/utils"; import { CORE_ALIASES } from "./core-aliases"; +import { isCoreAliasIdentifier, isDestructuredCoreMethodIdentifier } from "./core-method-resolve"; import { nonStringKind, NULL_KIND, UNDEFINED_KIND } from "./non-string-kind"; const createRule = ESLintUtils.RuleCreator(name => `https://github.com/github/gh-aw/tree/main/eslint-factory#${name}`); @@ -11,7 +12,7 @@ export const noCoreSetOutputNonStringRule = createRule({ hasSuggestions: true, docs: { description: - "Require core.setOutput value arguments to be explicit strings; passing numbers, booleans, null, undefined, or .length can silently produce unexpected string representations (e.g. 'null', 'true') in downstream GitHub Actions workflow expressions. Detects only calls in the form core.setOutput(name, value).", + "Require core.setOutput value arguments to be explicit strings; passing numbers, booleans, null, undefined, or .length can silently produce unexpected string representations (e.g. 'null', 'true') in downstream GitHub Actions workflow expressions. Detects calls in the form core.setOutput(name, value), aliased (const c = core; c.setOutput(...)), and destructured (const { setOutput } = core; setOutput(...)).", }, schema: [], messages: { @@ -29,16 +30,21 @@ export const noCoreSetOutputNonStringRule = createRule({ CallExpression(node) { const callee = node.callee; - // Must be a member expression: something.setOutput(...) - if (callee.type !== AST_NODE_TYPES.MemberExpression) return; + if (callee.type === AST_NODE_TYPES.MemberExpression) { + // Object must be a known @actions/core alias or a single-assignment alias (e.g. `const c = core`) + if (callee.object.type !== AST_NODE_TYPES.Identifier) return; + if (!CORE_ALIASES.has(callee.object.name) && !isCoreAliasIdentifier(callee.object, sourceCode)) return; - // Object must be a known @actions/core alias (`core` or `coreObj`) - if (callee.object.type !== AST_NODE_TYPES.Identifier || !CORE_ALIASES.has(callee.object.name)) return; - - // Property must be `setOutput` (direct or computed string-literal access) - const prop = callee.property; - const isSetOutputProp = (!callee.computed && prop.type === AST_NODE_TYPES.Identifier && prop.name === "setOutput") || (callee.computed && prop.type === AST_NODE_TYPES.Literal && prop.value === "setOutput"); - if (!isSetOutputProp) return; + // Property must be `setOutput` (direct or computed string-literal access) + const prop = callee.property; + const isSetOutputProp = (!callee.computed && prop.type === AST_NODE_TYPES.Identifier && prop.name === "setOutput") || (callee.computed && prop.type === AST_NODE_TYPES.Literal && prop.value === "setOutput"); + if (!isSetOutputProp) return; + } else if (callee.type === AST_NODE_TYPES.Identifier) { + // Destructured: `const { setOutput } = core; setOutput(...)` or `const { setOutput: alias } = core; alias(...)` + if (!isDestructuredCoreMethodIdentifier(callee, "setOutput", sourceCode)) return; + } else { + return; + } // core.setOutput expects exactly two arguments: (name, value) if (node.arguments.length !== 2) return; diff --git a/eslint-factory/src/rules/require-return-after-core-setfailed.ts b/eslint-factory/src/rules/require-return-after-core-setfailed.ts index c814d5f3a98..652fd375a27 100644 --- a/eslint-factory/src/rules/require-return-after-core-setfailed.ts +++ b/eslint-factory/src/rules/require-return-after-core-setfailed.ts @@ -1,5 +1,6 @@ -import { AST_NODE_TYPES, AST_TOKEN_TYPES, ESLintUtils, TSESLint, TSESTree } from "@typescript-eslint/utils"; +import { AST_NODE_TYPES, AST_TOKEN_TYPES, ESLintUtils, TSESTree } from "@typescript-eslint/utils"; import { CORE_ALIASES } from "./core-aliases"; +import { isCoreAliasIdentifier, isDestructuredCoreMethodIdentifier } from "./core-method-resolve"; const createRule = ESLintUtils.RuleCreator(name => `https://github.com/github/gh-aw/tree/main/eslint-factory#${name}`); @@ -166,63 +167,6 @@ export const requireReturnAfterCoreSetFailedRule = createRule({ create(context) { const sourceCode = context.sourceCode; - /** - * Checks whether an Identifier is a single-assignment alias for a core-like - * object (e.g., `const c = core`). Re-assigned let bindings are rejected. - * Local shadows (e.g., a parameter also named `c`) are excluded because they - * are found first in the scope chain and their definition type will not match. - */ - function isCoreAliasIdentifier(identifier: TSESTree.Identifier): boolean { - let currentScope: TSESLint.Scope.Scope | null = sourceCode.getScope(identifier); - while (currentScope !== null) { - const variable = currentScope.set.get(identifier.name); - if (variable !== undefined) { - if (variable.defs.length !== 1) return false; - const def = variable.defs[0]; - if (def.type !== "Variable") return false; - if (variable.references.some(ref => ref.isWrite() && !ref.init)) return false; - const declarator = def.node as TSESTree.VariableDeclarator; - if (!declarator.init) return false; - return declarator.id.type === AST_NODE_TYPES.Identifier && declarator.init.type === AST_NODE_TYPES.Identifier && isCoreLikeIdentifier(declarator.init.name); - } - currentScope = currentScope.upper; - } - return false; - } - - /** - * Checks whether an Identifier is the destructured `setFailed` binding from - * a core-like object (e.g., `const { setFailed } = core` or - * `const { setFailed: sf } = core` where `sf` is the identifier). - * Re-assigned let bindings are rejected. Local `function setFailed()` or - * parameter shadows are excluded via the `def.type !== "Variable"` guard. - */ - function isDestructuredSetFailedIdentifier(identifier: TSESTree.Identifier): boolean { - let currentScope: TSESLint.Scope.Scope | null = sourceCode.getScope(identifier); - while (currentScope !== null) { - const variable = currentScope.set.get(identifier.name); - if (variable !== undefined) { - if (variable.defs.length !== 1) return false; - const def = variable.defs[0]; - if (def.type !== "Variable") return false; - if (variable.references.some(ref => ref.isWrite() && !ref.init)) return false; - const declarator = def.node as TSESTree.VariableDeclarator; - if (!declarator.init) return false; - if (declarator.id.type === AST_NODE_TYPES.ObjectPattern && declarator.init.type === AST_NODE_TYPES.Identifier && isCoreLikeIdentifier(declarator.init.name)) { - return declarator.id.properties.some(prop => { - if (prop.type !== AST_NODE_TYPES.Property || prop.computed) return false; - const keyIsSetFailed = prop.key.type === AST_NODE_TYPES.Identifier && prop.key.name === "setFailed"; - const valueIsAlias = prop.value.type === AST_NODE_TYPES.Identifier && prop.value.name === identifier.name; - return keyIsSetFailed && valueIsAlias; - }); - } - return false; - } - currentScope = currentScope.upper; - } - return false; - } - /** * Returns true when the statement is a call to core.setFailed(...) in any * recognized form: @@ -244,12 +188,12 @@ export const requireReturnAfterCoreSetFailedRule = createRule({ const isComputedSetFailed = callee.computed && prop.type === AST_NODE_TYPES.Literal && prop.value === "setFailed"; if ((isNonComputedSetFailed || isComputedSetFailed) && obj.type === AST_NODE_TYPES.Identifier) { if (isCoreLikeIdentifier(obj.name)) return true; - if (isCoreAliasIdentifier(obj)) return true; + if (isCoreAliasIdentifier(obj, sourceCode)) return true; } } if (callee.type === AST_NODE_TYPES.Identifier) { - if (isDestructuredSetFailedIdentifier(callee)) return true; + if (isDestructuredCoreMethodIdentifier(callee, "setFailed", sourceCode)) return true; } return false;