UNPKG

eslint-plugin-lit

Version:
116 lines (115 loc) 3.88 kB
/** * @fileoverview Enforces calling `super` in lifecycle methods * @author James Garbutt <https://github.com/43081j> */ import { isLitClass } from '../util.js'; const methodNames = ['connectedCallback', 'disconnectedCallback', 'update']; //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ export const rule = { meta: { docs: { description: 'Enforces calling `super` in lifecycle methods', recommended: false, url: 'https://github.com/43081j/eslint-plugin-lit/blob/master/docs/rules/lifecycle-super.md' }, schema: [], messages: { callSuper: 'You must call `super.{{method}}` to avoid interrupting ' + 'the lit rendering lifecycle' } }, create(context) { // variables should be defined here let inElement = false; let currentMethod = null; let superSeen = false; //---------------------------------------------------------------------- // Helpers //---------------------------------------------------------------------- /** * Class entered * * @param {ESTree.Class} node Node entered * @return {void} */ function classEnter(node) { if (!isLitClass(node)) { return; } inElement = true; } /** * Class exited * * @return {void} */ function classExit() { inElement = false; } /** * Method entered * * @param {ESTree.MethodDefinition} node Node entered * @return {void} */ function methodEnter(node) { if (!inElement || node.static === true || node.kind !== 'method' || node.key.type !== 'Identifier' || !methodNames.includes(node.key.name)) { return; } currentMethod = node.key.name; } /** * Method exited * * @param {ESTree.MethodDefinition} node Node entered * @return {void} */ function methodExit(node) { if (currentMethod !== null && !superSeen) { context.report({ node, messageId: 'callSuper', data: { method: currentMethod } }); } currentMethod = null; superSeen = false; } /** * Call expression entered * @param {ESTree.CallExpression} node Node entered * @return {void} */ function callExpressionEnter(node) { if (currentMethod === null) { return; } if (node.callee.type === 'MemberExpression' && node.callee.object.type === 'Super' && node.callee.property.type === 'Identifier' && node.callee.property.name === currentMethod) { superSeen = true; } } //---------------------------------------------------------------------- // Public //---------------------------------------------------------------------- return { ClassExpression: (node) => classEnter(node), ClassDeclaration: (node) => classEnter(node), 'ClassExpression:exit': classExit, 'ClassDeclaration:exit': classExit, MethodDefinition: (node) => methodEnter(node), 'MethodDefinition:exit': methodExit, CallExpression: (node) => callExpressionEnter(node) }; } };