154 lines
4.0 KiB
JavaScript
154 lines
4.0 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);
|
|
},
|
|
};
|
|
},
|
|
};
|