UNPKG

@truenine/eslint9-config

Version:

ESLint 9 configuration package for Compose Client projects with TypeScript, Vue, and modern JavaScript support

1 lines 6.65 kB
{"version":3,"file":"call.mjs","names":[],"sources":["../../../src/rules/single-line/call.ts"],"sourcesContent":["import type {Rule} from 'eslint'\n\nconst MAX_LINE_LENGTH = 160\n\n/**\n * ESLint rule: prefer-single-line-call\n * Detects and fixes function calls that can be compressed to a single line.\n */\ninterface RuleOptions {maxLineLength?: number}\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'layout',\n docs: {description: 'Prefer single-line function calls when the result fits within max line length', recommended: false},\n fixable: 'code',\n schema: [{type: 'object', properties: {maxLineLength: {type: 'number', default: MAX_LINE_LENGTH}}, additionalProperties: false}],\n messages: {preferSingleLineCall: 'Function call can be written on a single line'}\n },\n create(context) {\n const {sourceCode} = context\n const options = (context.options[0] ?? {}) as RuleOptions\n const maxLineLength = options.maxLineLength ?? MAX_LINE_LENGTH\n\n function hasComments(node: Rule.Node): boolean { return sourceCode.getCommentsInside(node).length > 0 }\n function isNodeMultiLine(node: Rule.Node): boolean { return node.loc!.start.line !== node.loc!.end.line }\n function normalizeText(text: string): string { return text.split('\\n').map(l => l.trim()).join(' ').replaceAll(/\\s+/g, ' ').trim() }\n\n function getIndent(node: Rule.Node): string { /* 获取调用表达式的缩进 */\n const line = sourceCode.lines[node.loc!.start.line - 1]\n return /^(\\s*)/.exec(line)?.[1] ?? ''\n }\n\n function hasNestedObjectLiteral(node: Rule.Node): boolean { /* 检查节点是否包含嵌套的对象字面量 */\n if (node.type !== 'ObjectExpression') return false\n const objNode = node as Rule.Node & {properties: (Rule.Node & {value?: Rule.Node})[]}\n for (const prop of objNode.properties) {\n if (prop.type === 'Property' && (prop.value?.type === 'ObjectExpression' || prop.value?.type === 'ArrayExpression')) return true\n }\n return false\n }\n\n function hasComplexArgument(args: Rule.Node[]): boolean { /* 检查参数是否包含复杂结构 */\n for (const arg of args) {\n if (['ArrowFunctionExpression', 'FunctionExpression'].includes(arg.type)) return true /* 箭头函数或普通函数表达式 */\n if (arg.type === 'TemplateLiteral' && sourceCode.getText(arg).includes('\\n')) return true /* 模板字面量包含换行 */\n if (arg.type === 'ObjectExpression') {\n const objArg = arg as Rule.Node & {properties: Rule.Node[]}\n if (objArg.properties.length >= 5 || hasNestedObjectLiteral(arg)) return true /* 5 个及以上属性或嵌套对象 */\n }\n if (arg.type === 'ArrayExpression' && (arg as Rule.Node & {elements: Rule.Node[]}).elements.length >= 4) return true /* 数组字面量有 4 个及以上元素 */\n if (arg.type === 'CallExpression' && hasComplexArgument((arg as Rule.Node & {arguments: Rule.Node[]}).arguments)) return true /* 递归检查嵌套调用 */\n }\n return false\n }\n\n function isPartOfChainedCall(node: Rule.Node): boolean { /* 检查是否是链式调用的一部分 */\n const {parent} = node\n return parent?.type === 'MemberExpression' && parent.parent?.type === 'CallExpression'\n }\n\n function isChainedMethodCall(node: Rule.Node): boolean { /* 检查是否是链式方法调用 */\n const callNode = node as Rule.Node & {callee: Rule.Node}\n return callNode.callee.type === 'MemberExpression' && (callNode.callee as Rule.Node & {object: Rule.Node}).object.type === 'CallExpression'\n }\n\n return {\n CallExpression(node) {\n const callNode = node as Rule.Node & {callee: Rule.Node, arguments: Rule.Node[]}\n if (!isNodeMultiLine(callNode) || hasComments(callNode) || hasComplexArgument(callNode.arguments) || isPartOfChainedCall(callNode) || isChainedMethodCall(callNode)) return\n\n if (callNode.loc!.end.line - callNode.loc!.start.line + 1 > 4) return // 检查行数是否超过 4 行\n\n const calleeText = sourceCode.getText(callNode.callee)\n const argsText = callNode.arguments.map(arg => normalizeText(sourceCode.getText(arg))).join(', ')\n const singleLineText = `${calleeText}(${argsText})`\n\n if (singleLineText.length > 80) return // 检查字数是否超过 80\n if (getIndent(callNode).length + singleLineText.length > maxLineLength) return /* 如果超过最大行长度,不修复 */\n\n context.report({node, messageId: 'preferSingleLineCall', fix: fixer => fixer.replaceText(node, singleLineText)})\n }\n }\n }\n}\n\nexport default rule\n"],"mappings":";AAEA,MAAM,kBAAkB;AAQxB,MAAM,OAAwB;CAC5B,MAAM;EACJ,MAAM;EACN,MAAM;GAAC,aAAa;GAAiF,aAAa;GAAM;EACxH,SAAS;EACT,QAAQ,CAAC;GAAC,MAAM;GAAU,YAAY,EAAC,eAAe;IAAC,MAAM;IAAU,SAAS;IAAgB,EAAC;GAAE,sBAAsB;GAAM,CAAC;EAChI,UAAU,EAAC,sBAAsB,iDAAgD;EAClF;CACD,OAAO,SAAS;EACd,MAAM,EAAC,eAAc;EAErB,MAAM,iBADW,QAAQ,QAAQ,MAAM,EAAE,EACX,iBAAiB;EAE/C,SAAS,YAAY,MAA0B;AAAE,UAAO,WAAW,kBAAkB,KAAK,CAAC,SAAS;;EACpG,SAAS,gBAAgB,MAA0B;AAAE,UAAO,KAAK,IAAK,MAAM,SAAS,KAAK,IAAK,IAAI;;EACnG,SAAS,cAAc,MAAsB;AAAE,UAAO,KAAK,MAAM,KAAK,CAAC,KAAI,MAAK,EAAE,MAAM,CAAC,CAAC,KAAK,IAAI,CAAC,WAAW,QAAQ,IAAI,CAAC,MAAM;;EAElI,SAAS,UAAU,MAAyB;GAC1C,MAAM,OAAO,WAAW,MAAM,KAAK,IAAK,MAAM,OAAO;AACrD,UAAO,SAAS,KAAK,KAAK,GAAG,MAAM;;EAGrC,SAAS,uBAAuB,MAA0B;AACxD,OAAI,KAAK,SAAS,mBAAoB,QAAO;GAC7C,MAAM,UAAU;AAChB,QAAK,MAAM,QAAQ,QAAQ,WACzB,KAAI,KAAK,SAAS,eAAe,KAAK,OAAO,SAAS,sBAAsB,KAAK,OAAO,SAAS,mBAAoB,QAAO;AAE9H,UAAO;;EAGT,SAAS,mBAAmB,MAA4B;AACtD,QAAK,MAAM,OAAO,MAAM;AACtB,QAAI,CAAC,2BAA2B,qBAAqB,CAAC,SAAS,IAAI,KAAK,CAAE,QAAO;AACjF,QAAI,IAAI,SAAS,qBAAqB,WAAW,QAAQ,IAAI,CAAC,SAAS,KAAK,CAAE,QAAO;AACrF,QAAI,IAAI,SAAS,oBAEf;SADe,IACJ,WAAW,UAAU,KAAK,uBAAuB,IAAI,CAAE,QAAO;;AAE3E,QAAI,IAAI,SAAS,qBAAsB,IAA4C,SAAS,UAAU,EAAG,QAAO;AAChH,QAAI,IAAI,SAAS,oBAAoB,mBAAoB,IAA6C,UAAU,CAAE,QAAO;;AAE3H,UAAO;;EAGT,SAAS,oBAAoB,MAA0B;GACrD,MAAM,EAAC,WAAU;AACjB,UAAO,QAAQ,SAAS,sBAAsB,OAAO,QAAQ,SAAS;;EAGxE,SAAS,oBAAoB,MAA0B;GACrD,MAAM,WAAW;AACjB,UAAO,SAAS,OAAO,SAAS,sBAAuB,SAAS,OAA2C,OAAO,SAAS;;AAG7H,SAAO,EACL,eAAe,MAAM;GACnB,MAAM,WAAW;AACjB,OAAI,CAAC,gBAAgB,SAAS,IAAI,YAAY,SAAS,IAAI,mBAAmB,SAAS,UAAU,IAAI,oBAAoB,SAAS,IAAI,oBAAoB,SAAS,CAAE;AAErK,OAAI,SAAS,IAAK,IAAI,OAAO,SAAS,IAAK,MAAM,OAAO,IAAI,EAAG;GAI/D,MAAM,iBAAiB,GAFJ,WAAW,QAAQ,SAAS,OAAO,CAEjB,GADpB,SAAS,UAAU,KAAI,QAAO,cAAc,WAAW,QAAQ,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,CAChD;AAEjD,OAAI,eAAe,SAAS,GAAI;AAChC,OAAI,UAAU,SAAS,CAAC,SAAS,eAAe,SAAS,cAAe;AAExE,WAAQ,OAAO;IAAC;IAAM,WAAW;IAAwB,MAAK,UAAS,MAAM,YAAY,MAAM,eAAe;IAAC,CAAC;KAEnH;;CAEJ"}