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.

getter-return.js 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /**
  2. * @fileoverview Enforces that a return statement is present in property getters.
  3. * @author Aladdin-ADD(hh_2013@foxmail.com)
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Requirements
  8. //------------------------------------------------------------------------------
  9. const astUtils = require("../util/ast-utils");
  10. //------------------------------------------------------------------------------
  11. // Helpers
  12. //------------------------------------------------------------------------------
  13. const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/;
  14. /**
  15. * Checks a given code path segment is reachable.
  16. *
  17. * @param {CodePathSegment} segment - A segment to check.
  18. * @returns {boolean} `true` if the segment is reachable.
  19. */
  20. function isReachable(segment) {
  21. return segment.reachable;
  22. }
  23. /**
  24. * Gets a readable location.
  25. *
  26. * - FunctionExpression -> the function name or `function` keyword.
  27. *
  28. * @param {ASTNode} node - A function node to get.
  29. * @returns {ASTNode|Token} The node or the token of a location.
  30. */
  31. function getId(node) {
  32. return node.id || node;
  33. }
  34. //------------------------------------------------------------------------------
  35. // Rule Definition
  36. //------------------------------------------------------------------------------
  37. module.exports = {
  38. meta: {
  39. type: "problem",
  40. docs: {
  41. description: "enforce `return` statements in getters",
  42. category: "Possible Errors",
  43. recommended: true,
  44. url: "https://eslint.org/docs/rules/getter-return"
  45. },
  46. fixable: null,
  47. schema: [
  48. {
  49. type: "object",
  50. properties: {
  51. allowImplicit: {
  52. type: "boolean"
  53. }
  54. },
  55. additionalProperties: false
  56. }
  57. ],
  58. messages: {
  59. expected: "Expected to return a value in {{name}}.",
  60. expectedAlways: "Expected {{name}} to always return a value."
  61. }
  62. },
  63. create(context) {
  64. const options = context.options[0] || { allowImplicit: false };
  65. let funcInfo = {
  66. upper: null,
  67. codePath: null,
  68. hasReturn: false,
  69. shouldCheck: false,
  70. node: null
  71. };
  72. /**
  73. * Checks whether or not the last code path segment is reachable.
  74. * Then reports this function if the segment is reachable.
  75. *
  76. * If the last code path segment is reachable, there are paths which are not
  77. * returned or thrown.
  78. *
  79. * @param {ASTNode} node - A node to check.
  80. * @returns {void}
  81. */
  82. function checkLastSegment(node) {
  83. if (funcInfo.shouldCheck &&
  84. funcInfo.codePath.currentSegments.some(isReachable)
  85. ) {
  86. context.report({
  87. node,
  88. loc: getId(node).loc.start,
  89. messageId: funcInfo.hasReturn ? "expectedAlways" : "expected",
  90. data: {
  91. name: astUtils.getFunctionNameWithKind(funcInfo.node)
  92. }
  93. });
  94. }
  95. }
  96. /**
  97. * Checks whether a node means a getter function.
  98. * @param {ASTNode} node - a node to check.
  99. * @returns {boolean} if node means a getter, return true; else return false.
  100. */
  101. function isGetter(node) {
  102. const parent = node.parent;
  103. if (TARGET_NODE_TYPE.test(node.type) && node.body.type === "BlockStatement") {
  104. if (parent.kind === "get") {
  105. return true;
  106. }
  107. if (parent.type === "Property" && astUtils.getStaticPropertyName(parent) === "get" && parent.parent.type === "ObjectExpression") {
  108. // Object.defineProperty()
  109. if (parent.parent.parent.type === "CallExpression" &&
  110. astUtils.getStaticPropertyName(parent.parent.parent.callee) === "defineProperty") {
  111. return true;
  112. }
  113. // Object.defineProperties()
  114. if (parent.parent.parent.type === "Property" &&
  115. parent.parent.parent.parent.type === "ObjectExpression" &&
  116. parent.parent.parent.parent.parent.type === "CallExpression" &&
  117. astUtils.getStaticPropertyName(parent.parent.parent.parent.parent.callee) === "defineProperties") {
  118. return true;
  119. }
  120. }
  121. }
  122. return false;
  123. }
  124. return {
  125. // Stacks this function's information.
  126. onCodePathStart(codePath, node) {
  127. funcInfo = {
  128. upper: funcInfo,
  129. codePath,
  130. hasReturn: false,
  131. shouldCheck: isGetter(node),
  132. node
  133. };
  134. },
  135. // Pops this function's information.
  136. onCodePathEnd() {
  137. funcInfo = funcInfo.upper;
  138. },
  139. // Checks the return statement is valid.
  140. ReturnStatement(node) {
  141. if (funcInfo.shouldCheck) {
  142. funcInfo.hasReturn = true;
  143. // if allowImplicit: false, should also check node.argument
  144. if (!options.allowImplicit && !node.argument) {
  145. context.report({
  146. node,
  147. messageId: "expected",
  148. data: {
  149. name: astUtils.getFunctionNameWithKind(funcInfo.node)
  150. }
  151. });
  152. }
  153. }
  154. },
  155. // Reports a given function if the last path is reachable.
  156. "FunctionExpression:exit": checkLastSegment,
  157. "ArrowFunctionExpression:exit": checkLastSegment
  158. };
  159. }
  160. };