Ohm-Management - Projektarbeit B-ME
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.

no-useless-constructor.js 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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. type: "suggestion",
  133. docs: {
  134. description: "disallow unnecessary constructors",
  135. category: "ECMAScript 6",
  136. recommended: false,
  137. url: "https://eslint.org/docs/rules/no-useless-constructor"
  138. },
  139. schema: []
  140. },
  141. create(context) {
  142. /**
  143. * Checks whether a node is a redundant constructor
  144. * @param {ASTNode} node - node to check
  145. * @returns {void}
  146. */
  147. function checkForConstructor(node) {
  148. if (node.kind !== "constructor") {
  149. return;
  150. }
  151. const body = node.value.body.body;
  152. const ctorParams = node.value.params;
  153. const superClass = node.parent.parent.superClass;
  154. if (superClass ? isRedundantSuperCall(body, ctorParams) : (body.length === 0)) {
  155. context.report({
  156. node,
  157. message: "Useless constructor."
  158. });
  159. }
  160. }
  161. return {
  162. MethodDefinition: checkForConstructor
  163. };
  164. }
  165. };