summaryrefslogtreecommitdiff
path: root/tools/node_modules/eslint/lib/rules/getter-return.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/node_modules/eslint/lib/rules/getter-return.js')
-rw-r--r--tools/node_modules/eslint/lib/rules/getter-return.js177
1 files changed, 177 insertions, 0 deletions
diff --git a/tools/node_modules/eslint/lib/rules/getter-return.js b/tools/node_modules/eslint/lib/rules/getter-return.js
new file mode 100644
index 0000000000..6eb1efc00c
--- /dev/null
+++ b/tools/node_modules/eslint/lib/rules/getter-return.js
@@ -0,0 +1,177 @@
+/**
+ * @fileoverview Enforces that a return statement is present in property getters.
+ * @author Aladdin-ADD(hh_2013@foxmail.com)
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/;
+
+/**
+ * Checks a given code path segment is reachable.
+ *
+ * @param {CodePathSegment} segment - A segment to check.
+ * @returns {boolean} `true` if the segment is reachable.
+ */
+function isReachable(segment) {
+ return segment.reachable;
+}
+
+/**
+ * Gets a readable location.
+ *
+ * - FunctionExpression -> the function name or `function` keyword.
+ *
+ * @param {ASTNode} node - A function node to get.
+ * @returns {ASTNode|Token} The node or the token of a location.
+ */
+function getId(node) {
+ return node.id || node;
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "enforce `return` statements in getters",
+ category: "Possible Errors",
+ recommended: false
+ },
+ fixable: null,
+ schema: [
+ {
+ type: "object",
+ properties: {
+ allowImplicit: {
+ type: "boolean"
+ }
+ },
+ additionalProperties: false
+ }
+ ]
+ },
+
+ create(context) {
+
+ const options = context.options[0] || { allowImplicit: false };
+
+ let funcInfo = {
+ upper: null,
+ codePath: null,
+ hasReturn: false,
+ shouldCheck: false,
+ node: null
+ };
+
+ /**
+ * Checks whether or not the last code path segment is reachable.
+ * Then reports this function if the segment is reachable.
+ *
+ * If the last code path segment is reachable, there are paths which are not
+ * returned or thrown.
+ *
+ * @param {ASTNode} node - A node to check.
+ * @returns {void}
+ */
+ function checkLastSegment(node) {
+ if (funcInfo.shouldCheck &&
+ funcInfo.codePath.currentSegments.some(isReachable)
+ ) {
+ context.report({
+ node,
+ loc: getId(node).loc.start,
+ message: funcInfo.hasReturn
+ ? "Expected {{name}} to always return a value."
+ : "Expected to return a value in {{name}}.",
+ data: {
+ name: astUtils.getFunctionNameWithKind(funcInfo.node)
+ }
+ });
+ }
+ }
+
+ /**
+ * Checks whether a node means a getter function.
+ * @param {ASTNode} node - a node to check.
+ * @returns {boolean} if node means a getter, return true; else return false.
+ */
+ function isGetter(node) {
+ const parent = node.parent;
+
+ if (TARGET_NODE_TYPE.test(node.type) && node.body.type === "BlockStatement") {
+ if (parent.kind === "get") {
+ return true;
+ }
+ if (parent.type === "Property" && astUtils.getStaticPropertyName(parent) === "get" && parent.parent.type === "ObjectExpression") {
+
+ // Object.defineProperty()
+ if (parent.parent.parent.type === "CallExpression" &&
+ astUtils.getStaticPropertyName(parent.parent.parent.callee) === "defineProperty") {
+ return true;
+ }
+
+ // Object.defineProperties()
+ if (parent.parent.parent.type === "Property" &&
+ parent.parent.parent.parent.type === "ObjectExpression" &&
+ parent.parent.parent.parent.parent.type === "CallExpression" &&
+ astUtils.getStaticPropertyName(parent.parent.parent.parent.parent.callee) === "defineProperties") {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ return {
+
+ // Stacks this function's information.
+ onCodePathStart(codePath, node) {
+ funcInfo = {
+ upper: funcInfo,
+ codePath,
+ hasReturn: false,
+ shouldCheck: isGetter(node),
+ node
+ };
+ },
+
+ // Pops this function's information.
+ onCodePathEnd() {
+ funcInfo = funcInfo.upper;
+ },
+
+ // Checks the return statement is valid.
+ ReturnStatement(node) {
+ if (funcInfo.shouldCheck) {
+ funcInfo.hasReturn = true;
+
+ // if allowImplicit: false, should also check node.argument
+ if (!options.allowImplicit && !node.argument) {
+ context.report({
+ node,
+ message: "Expected to return a value in {{name}}.",
+ data: {
+ name: astUtils.getFunctionNameWithKind(funcInfo.node)
+ }
+ });
+ }
+ }
+ },
+
+ // Reports a given function if the last path is reachable.
+ "FunctionExpression:exit": checkLastSegment,
+ "ArrowFunctionExpression:exit": checkLastSegment
+ };
+ }
+};