@truenine/eslint9-config
Version:
ESLint 9 configuration package for Compose Client projects with TypeScript, Vue, and modern JavaScript support
1 lines • 16.3 kB
Source Map (JSON)
{"version":3,"file":"if.cjs","names":[],"sources":["../../../src/rules/single-line/if.ts"],"sourcesContent":["import type {Rule} from 'eslint'\n\nconst MAX_LINE_LENGTH = 160\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'layout',\n docs: {description: 'Prefer single-line if statements when possible', recommended: false},\n fixable: 'code',\n schema: [],\n messages: {preferSingleLine: 'If-else chain with simple statements should be single-line format', preferSingleLineBranch: 'Simple if/else branch should be single-line format'}\n },\n create(context) {\n const {sourceCode} = context\n\n function getSingleStatement(node: Rule.Node | null | undefined): Rule.Node | null { /* eslint-disable ts/no-unsafe-assignment */\n if (!node) return null\n if (node.type !== 'BlockStatement') return node\n\n const {body} = node as any\n if (!Array.isArray(body) || body.length !== 1) return null\n return body[0] as Rule.Node\n }\n\n function hasComments(node: Rule.Node): boolean {\n const comments = sourceCode.getCommentsInside(node)\n return comments.length > 0\n } /* eslint-enable ts/no-unsafe-assignment */\n\n function isSimpleStatement(stmt: Rule.Node | null): boolean {\n if (!stmt) return false\n return new Set(['ExpressionStatement', 'ReturnStatement', 'ThrowStatement', 'BreakStatement', 'ContinueStatement']).has(stmt.type)\n }\n\n function isNodeSingleLine(node: Rule.Node): boolean {\n return node.loc?.start.line === node.loc?.end.line\n }\n\n function normalizeConditionText(text: string): string {\n return text /* 将多行条件压缩成单行,处理 || 和 && 分隔的情况 */\n .split('\\n')\n .map(line => line.trim())\n .join(' ')\n .replaceAll(/\\s+/g, ' ')\n .trim()\n }\n\n function canConditionBeSingleLine(test: Rule.Node): boolean {\n const condText = normalizeConditionText(sourceCode.getText(test))\n return condText.length < MAX_LINE_LENGTH - 40 /* 条件本身不能太长 */\n }\n\n function collectIfChain(node: Rule.Node): {conditions: Rule.Node[], finalElse: Rule.Node | null} {\n const conditions: Rule.Node[] = []\n let current: Rule.Node | null = node\n\n while (current && current.type === 'IfStatement') {\n conditions.push(current)\n current = ('alternate' in current ? current.alternate : null) as Rule.Node | null\n }\n\n return {conditions, finalElse: current}\n }\n\n function canBranchBeSimplified(consequent: Rule.Node, test: Rule.Node): boolean {\n if (consequent.type !== 'BlockStatement') return false\n if (!canConditionBeSingleLine(test)) return false\n if (hasComments(consequent)) return false\n\n const stmt = getSingleStatement(consequent)\n if (!stmt || !isSimpleStatement(stmt)) return false\n if (!isNodeSingleLine(stmt)) return false\n\n const condText = normalizeConditionText(sourceCode.getText(test))\n const stmtText = sourceCode.getText(stmt)\n const lineLength = `if (${condText}) ${stmtText}`.length\n return lineLength < MAX_LINE_LENGTH\n }\n\n function canConvertToSingleLine(node: Rule.Node): boolean {\n const {conditions, finalElse} = collectIfChain(node)\n\n for (const cond of conditions) {\n if (!('consequent' in cond) || !('test' in cond)) return false\n\n const test = cond.test as Rule.Node\n if (!canConditionBeSingleLine(test)) return false\n\n const consequent = cond.consequent as Rule.Node\n if (hasComments(consequent)) return false\n\n const stmt = getSingleStatement(consequent)\n if (!stmt || !isSimpleStatement(stmt)) return false\n if (!isNodeSingleLine(stmt)) return false\n }\n\n if (finalElse) {\n if (hasComments(finalElse)) return false\n const stmt = getSingleStatement(finalElse)\n if (!stmt || !isSimpleStatement(stmt)) return false\n if (!isNodeSingleLine(stmt)) return false\n }\n\n const lines: string[] = []\n for (let i = 0; i < conditions.length; i++) {\n const cond = conditions[i]\n if (!('consequent' in cond) || !('test' in cond)) continue\n const stmt = getSingleStatement(cond.consequent as Rule.Node)!\n const condText = normalizeConditionText(sourceCode.getText(cond.test as Rule.Node))\n const stmtText = sourceCode.getText(stmt)\n const prefix = i === 0 ? 'if' : 'else if'\n lines.push(`${prefix} (${condText}) ${stmtText}`)\n }\n\n if (!finalElse) return lines.every(line => line.length < MAX_LINE_LENGTH)\n\n const stmt = getSingleStatement(finalElse)!\n lines.push(`else ${sourceCode.getText(stmt)}`)\n return lines.every(line => line.length < MAX_LINE_LENGTH)\n }\n\n function isAlreadySingleLine(node: Rule.Node): boolean {\n const {conditions, finalElse} = collectIfChain(node)\n\n for (const cond of conditions) {\n if (!('consequent' in cond)) return false\n const consequent = cond.consequent as Rule.Node\n if (consequent.type === 'BlockStatement') return false\n }\n\n if (finalElse && finalElse.type === 'BlockStatement') return false\n\n for (const cond of conditions) {\n if (!('consequent' in cond)) return false\n const consequent = cond.consequent as Rule.Node\n const startLine = cond.loc?.start.line\n const endLine = consequent.loc?.end.line\n if (startLine !== endLine) return false\n }\n\n return true\n }\n\n function isBranchAlreadySingleLine(consequent: Rule.Node, ifNode: Rule.Node): boolean {\n if (consequent.type === 'BlockStatement') return false\n return ifNode.loc?.start.line === consequent.loc?.end.line\n }\n\n return {\n IfStatement(node) {\n const {parent} = node\n if (parent?.type === 'IfStatement' && 'alternate' in parent && parent.alternate === node) return /* Skip if this is part of an else-if chain (will be handled by the root if) */\n\n if (!isAlreadySingleLine(node) && canConvertToSingleLine(node)) { /* First, try to convert the entire chain */\n context.report({\n node,\n messageId: 'preferSingleLine',\n fix(fixer) {\n const {conditions, finalElse} = collectIfChain(node)\n const indent = ' '.repeat(node.loc?.start.column ?? 0)\n const lines: string[] = []\n\n for (let i = 0; i < conditions.length; i++) {\n const cond = conditions[i]\n if (!('consequent' in cond) || !('test' in cond)) continue\n const stmt = getSingleStatement(cond.consequent as Rule.Node)!\n const condText = normalizeConditionText(sourceCode.getText(cond.test as Rule.Node))\n let stmtText = sourceCode.getText(stmt)\n\n if (!stmtText.endsWith(';') && !stmtText.endsWith('}')) stmtText = stmtText.trimEnd()\n\n const prefix = i === 0 ? 'if' : `${indent}else if`\n lines.push(`${prefix} (${condText}) ${stmtText}`)\n }\n\n if (!finalElse) return fixer.replaceText(node, lines.join('\\n'))\n\n const stmt = getSingleStatement(finalElse)!\n let stmtText = sourceCode.getText(stmt)\n if (!stmtText.endsWith(';') && !stmtText.endsWith('}')) stmtText = stmtText.trimEnd()\n lines.push(`${indent}else ${stmtText}`)\n return fixer.replaceText(node, lines.join('\\n'))\n }\n })\n return\n }\n\n const {conditions, finalElse} = collectIfChain(node) /* If entire chain can't be converted, try to simplify individual branches */\n\n const branchSimplifiable: boolean[] = [] /* Check which branches can be simplified */\n for (const cond of conditions) {\n if (!('consequent' in cond) || !('test' in cond)) {\n branchSimplifiable.push(false)\n continue\n }\n const consequent = cond.consequent as Rule.Node\n const test = cond.test as Rule.Node\n const canSimplify = !isBranchAlreadySingleLine(consequent, cond) && canBranchBeSimplified(consequent, test)\n branchSimplifiable.push(canSimplify)\n }\n\n let finalElseSimplifiable = false\n if (finalElse && finalElse.type === 'BlockStatement' && !hasComments(finalElse)) {\n const stmt = getSingleStatement(finalElse)\n if (stmt && isSimpleStatement(stmt) && isNodeSingleLine(stmt)) {\n const stmtText = sourceCode.getText(stmt)\n finalElseSimplifiable = stmtText.length < MAX_LINE_LENGTH - 20\n }\n }\n\n const hasSimplifiableBranch = branchSimplifiable.some(Boolean) || finalElseSimplifiable /* Check if there's anything to simplify */\n if (!hasSimplifiableBranch) return\n\n context.report({\n node,\n messageId: 'preferSingleLineBranch',\n fix(fixer) { /* Report on the root node and rebuild the entire chain */\n const indent = ' '.repeat(node.loc?.start.column ?? 0)\n const lines: string[] = []\n\n for (let i = 0; i < conditions.length; i++) {\n const cond = conditions[i]\n if (!('consequent' in cond) || !('test' in cond)) continue\n\n const consequent = cond.consequent as Rule.Node\n const test = cond.test as Rule.Node\n const condText = sourceCode.getText(test)\n const prefix = i === 0 ? 'if' : `${indent}else if`\n\n if (branchSimplifiable[i]) {\n const stmt = getSingleStatement(consequent)! /* Simplify this branch */\n let stmtText = sourceCode.getText(stmt)\n if (!stmtText.endsWith(';') && !stmtText.endsWith('}')) stmtText = stmtText.trimEnd()\n lines.push(`${prefix} (${condText}) ${stmtText}`)\n } else {\n const consequentText = sourceCode.getText(consequent) /* Keep original format (already single-line without braces) */\n lines.push(`${prefix} (${condText}) ${consequentText}`)\n }\n }\n\n if (finalElse) {\n if (finalElseSimplifiable) {\n const stmt = getSingleStatement(finalElse)!\n let stmtText = sourceCode.getText(stmt)\n if (!stmtText.endsWith(';') && !stmtText.endsWith('}')) stmtText = stmtText.trimEnd()\n lines.push(`${indent}else ${stmtText}`)\n } else {\n const elseText = sourceCode.getText(finalElse)\n lines.push(`${indent}else ${elseText}`)\n }\n }\n\n return fixer.replaceText(node, lines.join('\\n'))\n }\n })\n }\n }\n }\n}\n\nexport default rule\n"],"mappings":"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"}