Files
test-repo/scripts/tools/eslint-plugin-prettier-internal-rules/no-useless-ast-path-callback-parameter.js
T

150 lines
3.9 KiB
JavaScript

const MESSAGE_ID_PATH = "error/path";
const MESSAGE_ID_INDEX = "error/index";
const MESSAGE_ID_VALUE = "error/value";
const messages = {
[MESSAGE_ID_PATH]: "Use `{{name}}` directly instead of the first parameter.",
[MESSAGE_ID_INDEX]:
"Use `{{name}}.{{property}}` instead of the second parameter.",
[MESSAGE_ID_VALUE]:
"Use `{{name}}.{{property}}` instead of the third parameter.",
};
function checkPathParameter(context, callExpression) {
const [callback] = callExpression.arguments;
if (callback.params.length === 0) {
return;
}
const parameter = callback.params[0];
if (parameter.type !== "Identifier") {
return;
}
const objectName = callExpression.callee.object.name;
const problem = {
node: parameter,
messageId: MESSAGE_ID_PATH,
data: { name: objectName },
};
if (callback.params.length === 1) {
const { sourceCode } = context;
const variable =
parameter.name === objectName
? undefined
: sourceCode
.getDeclaredVariables(callback)
.find((variable) => variable.defs[0]?.name === parameter);
if (variable || parameter.name === objectName) {
problem.fix = function* (fixer) {
yield fixer.remove(parameter);
const tokenAfter = sourceCode.getTokenAfter(parameter);
if (tokenAfter.value === ",") {
yield fixer.remove(tokenAfter);
}
if (parameter.name !== objectName) {
for (const reference of variable.references) {
yield fixer.replaceText(reference.identifier, objectName);
}
}
};
}
}
context.report(problem);
}
function createIndexOrValueParameterChecker(parameterIndex) {
const settings =
parameterIndex === 1
? {
parameterName: "index",
messageId: MESSAGE_ID_INDEX,
property: "index",
}
: {
parameterName: "value",
messageId: MESSAGE_ID_VALUE,
property: "siblings",
};
return (context, callExpression) => {
const methodName = callExpression.callee.property.name;
if (methodName !== "each" && methodName !== "map") {
return;
}
const [callback] = callExpression.arguments;
if (callback.params.length < parameterIndex + 1) {
return;
}
const parameter = callback.params[parameterIndex];
const objectName = callExpression.callee.object.name;
const problem = {
node: parameter,
messageId: settings.messageId,
data: { name: objectName, property: settings.property },
};
context.report(problem);
};
}
const checkIndexParameter = createIndexOrValueParameterChecker(1);
const checkValueParameter = createIndexOrValueParameterChecker(2);
export default {
meta: {
type: "suggestion",
messages,
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);
checkIndexParameter(context, callExpression);
checkValueParameter(context, callExpression);
},
};
},
};