Blame view
node_modules/eslint/lib/rules/constructor-super.js
3.39 KB
c39994410
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
/** * @fileoverview A rule to verify `super()` callings in constructor. * @author Toru Nagashima * @copyright 2015 Toru Nagashima. All rights reserved. */ "use strict"; //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ module.exports = function(context) { /** * Searches a class node from ancestors of a node. * @param {Node} node - A node to get. * @returns {ClassDeclaration|ClassExpression|null} the found class node or `null`. */ function getClassInAncestor(node) { while (node) { if (node.type === "ClassDeclaration" || node.type === "ClassExpression") { return node; } node = node.parent; } /* istanbul ignore next */ return null; } /** * Checks whether or not a node is the null literal. * @param {Node} node - A node to check. * @returns {boolean} whether or not a node is the null literal. */ function isNullLiteral(node) { return node && node.type === "Literal" && node.value === null; } /** * Checks whether or not the current traversal context is on constructors. * @param {{scope: Scope}} item - A checking context to check. * @returns {boolean} whether or not the current traversal context is on constructors. */ function isOnConstructor(item) { return item && item.scope === context.getScope().variableScope.upper.variableScope; } // A stack for checking context. var stack = []; return { /** * Start checking. * @param {MethodDefinition} node - A target node. * @returns {void} */ "MethodDefinition": function(node) { if (node.kind !== "constructor") { return; } stack.push({ superCallings: [], scope: context.getScope().variableScope }); }, /** * Checks the result, then reports invalid/missing `super()`. * @param {MethodDefinition} node - A target node. * @returns {void} */ "MethodDefinition:exit": function(node) { if (node.kind !== "constructor") { return; } var result = stack.pop(); var classNode = getClassInAncestor(node); /* istanbul ignore if */ if (!classNode) { return; } if (classNode.superClass === null || isNullLiteral(classNode.superClass)) { result.superCallings.forEach(function(superCalling) { context.report(superCalling, "unexpected `super()`."); }); } else if (result.superCallings.length === 0) { context.report(node.key, "this constructor requires `super()`."); } }, /** * Checks the result of checking, then reports invalid/missing `super()`. * @param {MethodDefinition} node - A target node. * @returns {void} */ "CallExpression": function(node) { var item = stack[stack.length - 1]; if (isOnConstructor(item) && node.callee.type === "Super") { item.superCallings.push(node); } } }; }; module.exports.schema = []; |