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.

prefer-destructuring.js 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /**
  2. * @fileoverview Prefer destructuring from arrays and objects
  3. * @author Alex LaFroscia
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Rule Definition
  8. //------------------------------------------------------------------------------
  9. module.exports = {
  10. meta: {
  11. type: "suggestion",
  12. docs: {
  13. description: "require destructuring from arrays and/or objects",
  14. category: "ECMAScript 6",
  15. recommended: false,
  16. url: "https://eslint.org/docs/rules/prefer-destructuring"
  17. },
  18. schema: [
  19. {
  20. /*
  21. * old support {array: Boolean, object: Boolean}
  22. * new support {VariableDeclarator: {}, AssignmentExpression: {}}
  23. */
  24. oneOf: [
  25. {
  26. type: "object",
  27. properties: {
  28. VariableDeclarator: {
  29. type: "object",
  30. properties: {
  31. array: {
  32. type: "boolean"
  33. },
  34. object: {
  35. type: "boolean"
  36. }
  37. },
  38. additionalProperties: false
  39. },
  40. AssignmentExpression: {
  41. type: "object",
  42. properties: {
  43. array: {
  44. type: "boolean"
  45. },
  46. object: {
  47. type: "boolean"
  48. }
  49. },
  50. additionalProperties: false
  51. }
  52. },
  53. additionalProperties: false
  54. },
  55. {
  56. type: "object",
  57. properties: {
  58. array: {
  59. type: "boolean"
  60. },
  61. object: {
  62. type: "boolean"
  63. }
  64. },
  65. additionalProperties: false
  66. }
  67. ]
  68. },
  69. {
  70. type: "object",
  71. properties: {
  72. enforceForRenamedProperties: {
  73. type: "boolean"
  74. }
  75. },
  76. additionalProperties: false
  77. }
  78. ]
  79. },
  80. create(context) {
  81. const enabledTypes = context.options[0];
  82. const enforceForRenamedProperties = context.options[1] && context.options[1].enforceForRenamedProperties;
  83. let normalizedOptions = {
  84. VariableDeclarator: { array: true, object: true },
  85. AssignmentExpression: { array: true, object: true }
  86. };
  87. if (enabledTypes) {
  88. normalizedOptions = typeof enabledTypes.array !== "undefined" || typeof enabledTypes.object !== "undefined"
  89. ? { VariableDeclarator: enabledTypes, AssignmentExpression: enabledTypes }
  90. : enabledTypes;
  91. }
  92. //--------------------------------------------------------------------------
  93. // Helpers
  94. //--------------------------------------------------------------------------
  95. /**
  96. * @param {string} nodeType "AssignmentExpression" or "VariableDeclarator"
  97. * @param {string} destructuringType "array" or "object"
  98. * @returns {boolean} `true` if the destructuring type should be checked for the given node
  99. */
  100. function shouldCheck(nodeType, destructuringType) {
  101. return normalizedOptions &&
  102. normalizedOptions[nodeType] &&
  103. normalizedOptions[nodeType][destructuringType];
  104. }
  105. /**
  106. * Determines if the given node is accessing an array index
  107. *
  108. * This is used to differentiate array index access from object property
  109. * access.
  110. *
  111. * @param {ASTNode} node the node to evaluate
  112. * @returns {boolean} whether or not the node is an integer
  113. */
  114. function isArrayIndexAccess(node) {
  115. return Number.isInteger(node.property.value);
  116. }
  117. /**
  118. * Report that the given node should use destructuring
  119. *
  120. * @param {ASTNode} reportNode the node to report
  121. * @param {string} type the type of destructuring that should have been done
  122. * @returns {void}
  123. */
  124. function report(reportNode, type) {
  125. context.report({ node: reportNode, message: "Use {{type}} destructuring.", data: { type } });
  126. }
  127. /**
  128. * Check that the `prefer-destructuring` rules are followed based on the
  129. * given left- and right-hand side of the assignment.
  130. *
  131. * Pulled out into a separate method so that VariableDeclarators and
  132. * AssignmentExpressions can share the same verification logic.
  133. *
  134. * @param {ASTNode} leftNode the left-hand side of the assignment
  135. * @param {ASTNode} rightNode the right-hand side of the assignment
  136. * @param {ASTNode} reportNode the node to report the error on
  137. * @returns {void}
  138. */
  139. function performCheck(leftNode, rightNode, reportNode) {
  140. if (rightNode.type !== "MemberExpression" || rightNode.object.type === "Super") {
  141. return;
  142. }
  143. if (isArrayIndexAccess(rightNode)) {
  144. if (shouldCheck(reportNode.type, "array")) {
  145. report(reportNode, "array");
  146. }
  147. return;
  148. }
  149. if (shouldCheck(reportNode.type, "object") && enforceForRenamedProperties) {
  150. report(reportNode, "object");
  151. return;
  152. }
  153. if (shouldCheck(reportNode.type, "object")) {
  154. const property = rightNode.property;
  155. if (
  156. (property.type === "Literal" && leftNode.name === property.value) ||
  157. (property.type === "Identifier" && leftNode.name === property.name && !rightNode.computed)
  158. ) {
  159. report(reportNode, "object");
  160. }
  161. }
  162. }
  163. /**
  164. * Check if a given variable declarator is coming from an property access
  165. * that should be using destructuring instead
  166. *
  167. * @param {ASTNode} node the variable declarator to check
  168. * @returns {void}
  169. */
  170. function checkVariableDeclarator(node) {
  171. // Skip if variable is declared without assignment
  172. if (!node.init) {
  173. return;
  174. }
  175. // We only care about member expressions past this point
  176. if (node.init.type !== "MemberExpression") {
  177. return;
  178. }
  179. performCheck(node.id, node.init, node);
  180. }
  181. /**
  182. * Run the `prefer-destructuring` check on an AssignmentExpression
  183. *
  184. * @param {ASTNode} node the AssignmentExpression node
  185. * @returns {void}
  186. */
  187. function checkAssigmentExpression(node) {
  188. if (node.operator === "=") {
  189. performCheck(node.left, node.right, node);
  190. }
  191. }
  192. //--------------------------------------------------------------------------
  193. // Public
  194. //--------------------------------------------------------------------------
  195. return {
  196. VariableDeclarator: checkVariableDeclarator,
  197. AssignmentExpression: checkAssigmentExpression
  198. };
  199. }
  200. };