UNPKG

eslint-plugin-svelte

Version:
94 lines (93 loc) 3.73 kB
import { createRule } from '../utils/index.js'; import { getTypeScriptTools, isMethodSymbol, isPropertySignatureKind, isFunctionTypeKind, isMethodSignatureKind, isTypeReferenceKind, isIdentifierKind } from '../utils/ts-utils/index.js'; export default createRule('require-event-prefix', { meta: { docs: { description: 'require component event names to start with "on"', category: 'Stylistic Issues', conflictWithPrettier: false, recommended: false }, schema: [ { type: 'object', properties: { checkAsyncFunctions: { type: 'boolean' } }, additionalProperties: false } ], messages: { nonPrefixedFunction: 'Component event name must start with "on".' }, type: 'suggestion', conditions: [ { svelteVersions: ['5'], svelteFileTypes: ['.svelte'] } ] }, create(context) { const tsTools = getTypeScriptTools(context); if (!tsTools) { return {}; } const checkAsyncFunctions = context.options[0]?.checkAsyncFunctions ?? false; return { CallExpression(node) { const propsType = getPropsType(node, tsTools); if (propsType === undefined) { return; } for (const property of propsType.getProperties()) { if (isFunctionLike(property, tsTools) && !property.getName().startsWith('on') && (checkAsyncFunctions || !isFunctionAsync(property, tsTools))) { const declarationTsNode = property.getDeclarations()?.[0]; const declarationEstreeNode = declarationTsNode !== undefined ? tsTools.service.tsNodeToESTreeNodeMap.get(declarationTsNode) : undefined; context.report({ node: declarationEstreeNode ?? node, messageId: 'nonPrefixedFunction' }); } } } }; } }); function getPropsType(node, tsTools) { if (node.callee.type !== 'Identifier' || node.callee.name !== '$props' || node.parent.type !== 'VariableDeclarator') { return undefined; } const tsNode = tsTools.service.esTreeNodeToTSNodeMap.get(node.parent.id); if (tsNode === undefined) { return undefined; } return tsTools.service.program.getTypeChecker().getTypeAtLocation(tsNode); } function isFunctionLike(functionSymbol, tsTools) { return (isMethodSymbol(functionSymbol, tsTools.ts) || (functionSymbol.valueDeclaration !== undefined && isPropertySignatureKind(functionSymbol.valueDeclaration, tsTools.ts) && functionSymbol.valueDeclaration.type !== undefined && isFunctionTypeKind(functionSymbol.valueDeclaration.type, tsTools.ts))); } function isFunctionAsync(functionSymbol, tsTools) { return (functionSymbol.getDeclarations()?.some((declaration) => { if (!isMethodSignatureKind(declaration, tsTools.ts)) { return false; } if (declaration.type === undefined || !isTypeReferenceKind(declaration.type, tsTools.ts)) { return false; } return (isIdentifierKind(declaration.type.typeName, tsTools.ts) && declaration.type.typeName.escapedText === 'Promise'); }) ?? false); }