项目原始demo,不改动
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 
 

184 lines
5.4 KiB

  1. /**
  2. * @fileoverview Rule to flag the use of redundant constructors in classes.
  3. * @author Alberto Rodríguez
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Helpers
  8. //------------------------------------------------------------------------------
  9. /**
  10. * Checks whether a given array of statements is a single call of `super`.
  11. *
  12. * @param {ASTNode[]} body - An array of statements to check.
  13. * @returns {boolean} `true` if the body is a single call of `super`.
  14. */
  15. function isSingleSuperCall(body) {
  16. return (
  17. body.length === 1 &&
  18. body[0].type === "ExpressionStatement" &&
  19. body[0].expression.type === "CallExpression" &&
  20. body[0].expression.callee.type === "Super"
  21. );
  22. }
  23. /**
  24. * Checks whether a given node is a pattern which doesn't have any side effects.
  25. * Default parameters and Destructuring parameters can have side effects.
  26. *
  27. * @param {ASTNode} node - A pattern node.
  28. * @returns {boolean} `true` if the node doesn't have any side effects.
  29. */
  30. function isSimple(node) {
  31. return node.type === "Identifier" || node.type === "RestElement";
  32. }
  33. /**
  34. * Checks whether a given array of expressions is `...arguments` or not.
  35. * `super(...arguments)` passes all arguments through.
  36. *
  37. * @param {ASTNode[]} superArgs - An array of expressions to check.
  38. * @returns {boolean} `true` if the superArgs is `...arguments`.
  39. */
  40. function isSpreadArguments(superArgs) {
  41. return (
  42. superArgs.length === 1 &&
  43. superArgs[0].type === "SpreadElement" &&
  44. superArgs[0].argument.type === "Identifier" &&
  45. superArgs[0].argument.name === "arguments"
  46. );
  47. }
  48. /**
  49. * Checks whether given 2 nodes are identifiers which have the same name or not.
  50. *
  51. * @param {ASTNode} ctorParam - A node to check.
  52. * @param {ASTNode} superArg - A node to check.
  53. * @returns {boolean} `true` if the nodes are identifiers which have the same
  54. * name.
  55. */
  56. function isValidIdentifierPair(ctorParam, superArg) {
  57. return (
  58. ctorParam.type === "Identifier" &&
  59. superArg.type === "Identifier" &&
  60. ctorParam.name === superArg.name
  61. );
  62. }
  63. /**
  64. * Checks whether given 2 nodes are a rest/spread pair which has the same values.
  65. *
  66. * @param {ASTNode} ctorParam - A node to check.
  67. * @param {ASTNode} superArg - A node to check.
  68. * @returns {boolean} `true` if the nodes are a rest/spread pair which has the
  69. * same values.
  70. */
  71. function isValidRestSpreadPair(ctorParam, superArg) {
  72. return (
  73. ctorParam.type === "RestElement" &&
  74. superArg.type === "SpreadElement" &&
  75. isValidIdentifierPair(ctorParam.argument, superArg.argument)
  76. );
  77. }
  78. /**
  79. * Checks whether given 2 nodes have the same value or not.
  80. *
  81. * @param {ASTNode} ctorParam - A node to check.
  82. * @param {ASTNode} superArg - A node to check.
  83. * @returns {boolean} `true` if the nodes have the same value or not.
  84. */
  85. function isValidPair(ctorParam, superArg) {
  86. return (
  87. isValidIdentifierPair(ctorParam, superArg) ||
  88. isValidRestSpreadPair(ctorParam, superArg)
  89. );
  90. }
  91. /**
  92. * Checks whether the parameters of a constructor and the arguments of `super()`
  93. * have the same values or not.
  94. *
  95. * @param {ASTNode} ctorParams - The parameters of a constructor to check.
  96. * @param {ASTNode} superArgs - The arguments of `super()` to check.
  97. * @returns {boolean} `true` if those have the same values.
  98. */
  99. function isPassingThrough(ctorParams, superArgs) {
  100. if (ctorParams.length !== superArgs.length) {
  101. return false;
  102. }
  103. for (let i = 0; i < ctorParams.length; ++i) {
  104. if (!isValidPair(ctorParams[i], superArgs[i])) {
  105. return false;
  106. }
  107. }
  108. return true;
  109. }
  110. /**
  111. * Checks whether the constructor body is a redundant super call.
  112. *
  113. * @param {Array} body - constructor body content.
  114. * @param {Array} ctorParams - The params to check against super call.
  115. * @returns {boolean} true if the construtor body is redundant
  116. */
  117. function isRedundantSuperCall(body, ctorParams) {
  118. return (
  119. isSingleSuperCall(body) &&
  120. ctorParams.every(isSimple) &&
  121. (
  122. isSpreadArguments(body[0].expression.arguments) ||
  123. isPassingThrough(ctorParams, body[0].expression.arguments)
  124. )
  125. );
  126. }
  127. //------------------------------------------------------------------------------
  128. // Rule Definition
  129. //------------------------------------------------------------------------------
  130. module.exports = {
  131. meta: {
  132. docs: {
  133. description: "disallow unnecessary constructors",
  134. category: "ECMAScript 6",
  135. recommended: false,
  136. url: "https://eslint.org/docs/rules/no-useless-constructor"
  137. },
  138. schema: []
  139. },
  140. create(context) {
  141. /**
  142. * Checks whether a node is a redundant constructor
  143. * @param {ASTNode} node - node to check
  144. * @returns {void}
  145. */
  146. function checkForConstructor(node) {
  147. if (node.kind !== "constructor") {
  148. return;
  149. }
  150. const body = node.value.body.body;
  151. const ctorParams = node.value.params;
  152. const superClass = node.parent.parent.superClass;
  153. if (superClass ? isRedundantSuperCall(body, ctorParams) : (body.length === 0)) {
  154. context.report({
  155. node,
  156. message: "Useless constructor."
  157. });
  158. }
  159. }
  160. return {
  161. MethodDefinition: checkForConstructor
  162. };
  163. }
  164. };