@nighttrax/eslint-config-tsx
Version:
NiGhTTraX's ESLint config for TSX apps
92 lines (82 loc) • 3.35 kB
JavaScript
import { merge } from "@eslint-react/kit";
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
/**
* Enforce arrow function definitions for function components.
* @returns {import("@eslint-react/kit").RuleFunction}
*/
export function functionComponentDefinition() {
return (context, { collect, hint }) => {
const { query, visitor } = collect.components(context, {
hint:
hint.component.Default &
~hint.component.DoNotIncludeFunctionDefinedAsObjectMethod,
});
return merge(visitor, {
"Program:exit"(program) {
// ─── Iterate all components ────────────────────
for (const { node } of query.all(program)) {
// › Guard: must not already be arrow function
if (node.type === AST_NODE_TYPES.ArrowFunctionExpression) {
continue;
}
context.report({
node,
message:
"Function components must be defined with arrow functions.",
suggest: [
{
desc: "Convert to arrow function.",
fix(fixer) {
const src = context.sourceCode;
if (node.generator) {
return null;
}
const prefix = node.async ? "async " : "";
const typeParams = node.typeParameters
? src.getText(node.typeParameters)
: "";
const params = `(${node.params.map((p) => src.getText(p)).join(", ")})`;
const returnType = node.returnType
? src.getText(node.returnType)
: "";
const body = src.getText(node.body);
// ─── Case: function declaration ──────────────
if (
node.type === AST_NODE_TYPES.FunctionDeclaration &&
node.id
) {
return fixer.replaceText(
node,
`const ${node.id.name} = ${prefix}${typeParams}${params}${returnType} => ${body};`,
);
}
// ─── Case: function expression in variable ───
if (
node.type === AST_NODE_TYPES.FunctionExpression &&
node.parent.type === AST_NODE_TYPES.VariableDeclarator
) {
return fixer.replaceText(
node,
`${prefix}${typeParams}${params}${returnType} => ${body}`,
);
}
// ─── Case: object method shorthand ───────────
if (
node.type === AST_NODE_TYPES.FunctionExpression &&
node.parent.type === AST_NODE_TYPES.Property
) {
return fixer.replaceText(
node.parent,
`${src.getText(node.parent.key)}: ${prefix}${typeParams}${params}${returnType} => ${body}`,
);
}
return null;
},
},
],
});
}
},
});
};
}