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