Skip to content

Commit fa37ccd

Browse files
authored
new copy
1 parent e8140f3 commit fa37ccd

File tree

1 file changed

+98
-33
lines changed

1 file changed

+98
-33
lines changed

eslint.config.ts

Lines changed: 98 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -251,25 +251,25 @@ export default defineConfig(
251251
//#endregion
252252

253253
{
254-
name: 'custom',
254+
name: "custom",
255255
plugins: {
256256
custom: {
257257
rules: {
258-
'no-arrow-parameter-types': {
258+
"no-arrow-parameter-types": {
259259
meta: {
260-
fixable: 'code',
260+
fixable: "code",
261261
hasSuggestions: true,
262-
type: 'suggestion',
263-
dialects: ['typescript'],
262+
type: "suggestion",
263+
dialects: ["typescript"],
264264
schema: [
265265
{
266-
type: 'object',
266+
type: "object",
267267
properties: {
268268
allowOptional: {
269-
type: 'boolean',
269+
type: "boolean",
270270
default: false,
271271
description:
272-
'Allow type annotations when the parameter is optional. Sometimes useful for overloaded functions.',
272+
"Allow type annotations when the parameter is optional. Sometimes useful for overloaded functions.",
273273
},
274274
},
275275
},
@@ -288,12 +288,12 @@ export default defineConfig(
288288
const paramsWithTypeAnnotation = node.params.filter(
289289
(
290290
// @ts-expect-error: will be inferred when moved into an official plugin
291-
param
292-
) => param.typeAnnotation !== undefined
291+
param,
292+
) => param.typeAnnotation !== undefined,
293293
);
294294

295295
const isCatchClause =
296-
node.parent.callee?.property?.name === 'catch';
296+
node.parent.callee?.property?.name === "catch";
297297

298298
if (paramsWithTypeAnnotation.length > 0 && !isCatchClause) {
299299
for (const param of paramsWithTypeAnnotation) {
@@ -304,51 +304,116 @@ export default defineConfig(
304304
context.report({
305305
node: param,
306306
message:
307-
'Arrow function parameters should not have type annotations. Instead the Object where the operation is used should be typed correctly.',
307+
"Arrow function parameters should not have type annotations. Instead the Object where the operation is used should be typed correctly.",
308308
fix(fixer) {
309309
if (param.optional) {
310310
return null;
311311
}
312312

313-
// TODO @Shinigami92 2025-06-16: Handle async arrow functions
314-
if (node.parent.type === 'VariableDeclarator') {
315-
const variableDeclaratorNode = node.parent;
313+
if (
314+
node.parent.type === "VariableDeclarator" &&
315+
!node.parent.id.typeAnnotation
316+
) {
317+
const variableDeclarationNode = node.parent;
316318

317-
return [
318-
// Remove ` =>`
319+
const isAsyncFunction: boolean = node.async;
320+
321+
const isBodyBlockStatement =
322+
node.body.type === "BlockStatement";
323+
324+
const isBodyJSXElement =
325+
node.body.type === "JSXElement";
326+
327+
const hasReturnType = node.returnType !== undefined;
328+
329+
const lastParam = node.params.at(-1);
330+
331+
const paramIdDifferentLine =
332+
lastParam.loc.start.line !==
333+
variableDeclarationNode.id.loc.end.line;
334+
335+
const paramBlockDifferentLine =
336+
lastParam.loc.end.line !==
337+
node.body.loc.start.line;
338+
339+
const behindClosingParenthesis = hasReturnType
340+
? (node.returnType.range[1] as number)
341+
: (lastParam.range[1] as number) + ")".length;
342+
343+
const fixes = [
344+
// Removes `=> `
319345
fixer.replaceTextRange(
320-
[node.body.range[0] - 3, node.body.range[0]],
321-
''
346+
[
347+
behindClosingParenthesis,
348+
node.body.range[0] as number,
349+
],
350+
!hasReturnType &&
351+
paramBlockDifferentLine &&
352+
paramIdDifferentLine
353+
? ")"
354+
: "",
322355
),
323-
// Remove ` = `
356+
// Removes ` = ` or ` = async `
324357
fixer.replaceTextRange(
325358
[
326-
variableDeclaratorNode.id.range[1],
327-
variableDeclaratorNode.init.range[0],
359+
variableDeclarationNode.id.range[1] as number,
360+
(variableDeclarationNode.init
361+
.range[0] as number) +
362+
(isAsyncFunction ? "async ".length : 0),
328363
],
329-
''
364+
"",
330365
),
331-
// Replace `const ` with `function `
366+
// Replaces `const ` with `function ` or `async function `
332367
fixer.replaceTextRange(
333368
[
334-
variableDeclaratorNode.parent.range[0],
335-
variableDeclaratorNode.range[0],
369+
variableDeclarationNode.parent
370+
.range[0] as number,
371+
variableDeclarationNode.range[0] as number,
336372
],
337-
'function '
373+
isAsyncFunction
374+
? "async function "
375+
: "function ",
338376
),
339377
];
378+
379+
// If the body is not a BlockStatement, we need to wrap it in curly braces
380+
if (!isBodyBlockStatement) {
381+
fixes.push(
382+
fixer.insertTextBefore(
383+
node.body,
384+
`{return ${isBodyJSXElement ? "(" : ""}`,
385+
),
386+
fixer.insertTextAfter(
387+
node.body,
388+
`${isBodyJSXElement ? ")" : ""}}`,
389+
),
390+
);
391+
392+
if (isBodyJSXElement) {
393+
fixes.push(
394+
fixer.removeRange([
395+
node.body.range[1] as number,
396+
node.range[1] as number,
397+
]),
398+
);
399+
}
400+
}
401+
402+
return fixes;
340403
}
341404

342-
return fixer.removeRange(param.typeAnnotation.range);
405+
return fixer.removeRange(
406+
param.typeAnnotation.range as [number, number],
407+
);
343408
},
344409
suggest: [
345410
{
346-
desc: 'Remove type annotation',
411+
desc: "Remove type annotation",
347412
fix(fixer) {
348413
if (param.optional) {
349414
return fixer.removeRange([
350-
param.typeAnnotation.range[0] - 1, // Remove the `?` before the type annotation
351-
param.typeAnnotation.range[1],
415+
(param.typeAnnotation.range[0] as number) - 1, // Remove the `?` before the type annotation
416+
param.typeAnnotation.range[1] as number,
352417
]);
353418
}
354419

@@ -367,7 +432,7 @@ export default defineConfig(
367432
},
368433
},
369434
rules: {
370-
'custom/no-arrow-parameter-types': ['error', { allowOptional: true }],
435+
"custom/no-arrow-parameter-types": ["error", { allowOptional: true }],
371436
},
372-
}
437+
},
373438
);

0 commit comments

Comments
 (0)