@yinxulai/eslint-plugin-peculiar
v1.0.4
Published
Peculiar ESLint plugin with custom function-related rules: definition allowance, signature linebreaks, and maximum parameter count.
Downloads
758
Maintainers
Readme
@yinxulai/eslint-plugin-peculiar
一个聚焦"函数定义"相关规则的 ESLint 插件:用 TypeScript 编写。
提供三个规则:
func-definition— 配置允许哪些种类的函数定义func-signature-linebreak— 控制函数签名的换行风格func-param-destructuring— 禁止在函数参数中使用解构模式
安装
要求 ESLint ≥ 8.40(用到了 context.sourceCode 等较新的 API)。
npm install --save-dev @yinxulai/eslint-plugin-peculiar eslint使用
旧式配置 (.eslintrc)
{
"plugins": ["@yinxulai/peculiar"],
"rules": {
"@yinxulai/peculiar/func-definition": "warn",
"@yinxulai/peculiar/func-signature-linebreak": ["warn", { "style": "single" }],
"@yinxulai/peculiar/func-param-destructuring": "warn"
}
}或使用预设:
{
"extends": ["plugin:@yinxulai/peculiar/recommended"]
// 或 "plugin:@yinxulai/peculiar/strict"
}Flat 配置 (eslint.config.js)
使用预设(推荐,命名空间短化为 peculiar):
import peculiar from '@yinxulai/eslint-plugin-peculiar'
export default [
...peculiar.configs['flat/recommended'],
// 或者: ...peculiar.configs['flat/strict']
]或手动注册插件并按需配置(命名空间必须和 plugins 的 key 一致):
import peculiar from '@yinxulai/eslint-plugin-peculiar'
export default [
{
plugins: { peculiar },
rules: {
'peculiar/func-definition': 'warn',
'peculiar/func-signature-linebreak': ['warn', { style: 'single' }],
'peculiar/func-param-destructuring': 'warn',
},
},
]预设
recommended / flat/recommended 与 strict / flat/strict 的 rule 配置完全一致,仅严重度不同(warn vs error):
| 规则 | 行为 |
| --- | --- |
| func-definition | 都允许(不传 allow = 4 种函数定义全开) |
| func-signature-linebreak | 不允许换行({ style: 'single' },强制签名单行) |
| func-param-destructuring | 仅允许箭头函数解构({ allowIn: ['arrow'] },function / method 仍禁用) |
func-definition与func-param-destructuring的"默认方向"是相反的:
func-definition不传allow= 4 种函数定义都允许func-param-destructuring不传allowIn= 全部禁止原因:前者的目标是"白名单"(开箱即用),后者的目标是"黑名单"(更严的代码规范)。
覆盖范围
所有规则都基于 ESLint/ESTree 的函数节点 触发,Visitor 访问以下节点类型:
| 节点类型 | 覆盖说明 |
| --- | --- |
| FunctionDeclaration | 顶层 function foo() {} 声明 |
| FunctionExpression | const f = function () {} 表达式,及 class/object 方法内部的函数 |
| ArrowFunctionExpression | const f = () => {} 箭头函数 |
| TSDeclareFunction | declare function foo(): void TS 声明(仅 func-definition 视为 declaration) |
类与对象方法:class A { foo() {} } 里的 foo 是 FunctionExpression,其 .parent 是 MethodDefinition,会被归类为 method。const o = { foo() {} } 里的 foo 同理(.parent 是 Property,且 method === true)。
嵌套函数:Visitor 会递归访问嵌套函数,但分类时只看直接父节点(isInsideMethod)。
规则
func-definition
配置允许的函数定义种类。
allow 选项(数组,元素可选 declaration / expression / arrow / method):
| kind | 含义 | 示例 |
| --- | --- | --- |
| declaration | 函数声明 | function foo() {} |
| expression | 函数表达式 | const foo = function () {} |
| arrow | 箭头函数 | const foo = () => {} |
| method | 类/对象方法 | class A { foo() {} } |
默认:全部允许。
// 禁用函数声明和函数表达式,只允许箭头和方法
{ "@yinxulai/peculiar/func-definition": ["error", { "allow": ["arrow", "method"] }] }数组为空 = 全部禁用。 数组含未知值(非
declaration/expression/arrow/method)会作为配置错误上报invalidAllowOption,而不是 schema 报错。
func-signature-linebreak
控制函数签名的换行风格。
| style | 行为 |
| --- | --- |
| single | 签名必须一行 |
| multiple | 签名必须多行,每个参数独占一行 |
| consistent | 签名要么全在一行,要么多行且每个参数独占一行(默认) |
附加选项 maxLength:单行签名字符数超过该值时,必须改为多行(每个参数独占一行)。计算的是 ( 与 ) 之间(不含括号本身)的字符数,含注释。 显式写了 style: 'single' + maxLength 时,过长依然会触发 signatureTooLong 并自动修复为多行。
// 强制单行(不允许换行)
{ "@yinxulai/peculiar/func-signature-linebreak": ["error", { "style": "single" }] }
// 强制多行,每个参数独占一行
{ "@yinxulai/peculiar/func-signature-linebreak": ["error", { "style": "multiple" }] }
// 允许单行,但超过 80 字符必须多行
{ "@yinxulai/peculiar/func-signature-linebreak": ["error", { "style": "consistent", "maxLength": 80 }] }不报错的场景:参数 < 2 个(没东西可换行)。
fix 安全护栏:自动修复仅在签名 () 内"无参数外注释"时生效。如果参数之间 / 之前 / 之后有内联块/行注释,fix 会只 report 不 fix(output: null),把决定权交给人工。
func-param-destructuring
禁止在函数参数中使用解构模式(ObjectPattern / ArrayPattern),包括 TypeScript 类型注解的情况。
allowIn 选项(数组,元素可选 function / arrow / method):
| kind | 含义 | 示例 |
| --- | --- | --- |
| function | 顶层函数声明/表达式 | function foo() {} / const foo = function () {} |
| arrow | 箭头函数 | const foo = () => {} |
| method | 类/对象方法 | class A { foo() {} } / const o = { foo() {} } |
默认:全部不允许(不传该选项 = 全部禁用,与 func-definition 默认方向相反)。
// 仅允许箭头函数解构
{ "@yinxulai/peculiar/func-param-destructuring": ["error", { "allowIn": ["arrow"] }] }示例:
// ❌ 报错
function Test({ a, b, c }: Props) {}
const handler = ({ event }) => doSomething(event)
class A { method([x, y]) {} }
// ✅ 不报错(重写为显式参数)
function Test(props: Props) { const { a, b, c } = props }
const handler = (event) => doSomething(event)
class A { method(coord) {} }
- 同时检查
ObjectPattern和ArrayPattern:function f([a, b]) {}也会被禁止。- TypeScript 类型注解不影响检查:
function f({ a }: { a: string }) {}仍然报错(param 节点本身就是ObjectPattern)。- 解构出来的属性是否被使用不在本规则范围,使用官方的
no-unused-vars。- 用途之一是绕过
max-params计数 ——function f({a, b, c, d, e})在官方max-params里只算 1 个参数,启用本规则可强制显式书写。
fix 条件:自动修复仅在"安全"场景下提供 —— 即:
- 函数体是
BlockStatement(不是箭头表达式体) - 没有
this形参(避免改写挪动其它形参索引) - 解构形参没有外层默认值(避免把默认值从 Pattern 上剥到 Identifier 上)
不满足上述条件时仍会报 paramDestructuring,但不带 fix。
开发
npm install
npm run build # tsc → output/ (test 文件不会进 output)
npm test # pretest (tsc --noEmit) + vitest 跑全部规则 + 插件结构测试
npm run coverage # 附带 v8 覆盖率报告测试栈:Vitest + ESLint 9 提供的 RuleTester(从 eslint 直接 import)。测试用 TypeScript 编写,并与对应实现文件并列放:
source/
index.ts
index.test.ts # 插件结构测试
rules/
func-definition.ts
func-definition.test.ts # 规则测试
func-param-destructuring.ts
func-param-destructuring.test.ts
func-signature-linebreak.ts
func-signature-linebreak.test.ts
utils/
function-helpers.tstsc 通过 tsconfig.json 的 exclude: ["**/*.test.ts"] 把测试文件挡在 output/ 外,不会污染发布包。npm test 走 pretest hook 跑 tsc --noEmit,确保发布前类型已干净。
协议
ISC
