Forbid rename path in callbacks (#18038)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
fisker Cheungandautofix-ci[bot] authored and GitHub committed 2025-10-11 01:46:03 +08:00
1 parent 05b1a783d1
commit 858ace6ffa
16 files changed
+176 -35

No files matched your search

@@ -0,0 +1,104 @@
const MESSAGE_ID_PATH = "error/path";
function checkPathParameter(context, callExpression) {
const [callback] = callExpression.arguments;
if (callback.params.length === 0) {
return;
}
const pathParameter = callback.params[0];
if (pathParameter.type !== "Identifier") {
return;
}
const objectName = callExpression.callee.object.name;
const problem = {
node: pathParameter,
messageId: MESSAGE_ID_PATH,
data: { name: objectName },
};
if (callback.params.length === 1) {
const { sourceCode } = context;
const variable =
pathParameter.name === objectName
? undefined
: sourceCode
.getDeclaredVariables(callback)
.find((variable) => variable.defs[0]?.name === pathParameter);
if (variable || pathParameter.name === objectName) {
problem.fix = function* (fixer) {
yield fixer.remove(pathParameter);
const tokenAfter = sourceCode.getTokenAfter(pathParameter);
if (tokenAfter.value === ",") {
yield fixer.remove(tokenAfter);
}
if (pathParameter.name !== objectName) {
for (const reference of variable.references) {
yield fixer.replaceText(reference.identifier, objectName);
}
}
};
}
}
context.report(problem);
}
export default {
meta: {
type: "suggestion",
messages: {
[MESSAGE_ID_PATH]:
"Use `{{name}}` directly instead of the first parameter.",
},
fixable: "code",
},
create(context) {
return {
CallExpression(callExpression) {
const { callee } = callExpression;
if (
!(
!callExpression.optional &&
callExpression.arguments.length > 0 &&
callee.type === "MemberExpression" &&
!callee.optional &&
!callee.computed &&
callee.object.type === "Identifier" &&
callee.property.type === "Identifier" &&
(callee.property.name === "call" ||
callee.property.name === "callParent" ||
callee.property.name === "each" ||
callee.property.name === "map")
)
) {
return;
}
const objectName = callee.object.name;
if (!(objectName === "path" || objectName.endsWith("Path"))) {
return;
}
const [callback] = callExpression.arguments;
if (
!(
callback.type === "FunctionExpression" ||
callback.type === "ArrowFunctionExpression"
)
) {
return;
}
checkPathParameter(context, callExpression);
},
};
},
};
@@ -9,7 +9,7 @@
"license": "MIT",
"scripts": {
"test": "node test.js",
"test-coverage": "npx nyc node test.js"
"test-coverage": "yarn dlx c8 node test.js"
},
"packageManager": "yarn@4.10.3"
}
@@ -949,3 +949,48 @@ test("massage-ast-parameter-names", {
},
],
});
test("no-useless-ast-path-callback-parameter", {
valid: [
"path.call?.((childPath) => childPath)",
"path?.call((childPath) => childPath)",
"path[call]((childPath) => childPath)",
"path.notCall((childPath) => childPath)",
"not_ast_path.call((childPath) => childPath)",
"path.call(({first},) => first)",
"path.call((...a) => a)",
"path.call(notFunctionExpression)",
],
invalid: [
...["call", "callParent", "each", "map"].map((method) => ({
code: `path.${method}((childPath) => childPath)`,
output: `path.${method}(() => path)`,
errors: 1,
})),
{
code: "path.call(function(childPath){childPath})",
output: "path.call(function(){path})",
errors: 1,
},
{
code: "path.call((childPath,) => childPath)",
output: "path.call(() => path)",
errors: 1,
},
{
code: "path.each((childPath,index, foo) => {})",
output: null,
errors: 1,
},
{
code: "fooPath.call((childPath) => childPath)",
output: "fooPath.call(() => fooPath)",
errors: 1,
},
{
code: "path.call((path) => path)",
output: "path.call(() => path)",
errors: 1,
},
],
});