]>
git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/rules/class-methods-use-this.js
beb742d93a793824b88ef23f3299c06adaff680b
2 * @fileoverview Rule to enforce that all class methods use 'this'.
3 * @author Patrick Williams
8 //------------------------------------------------------------------------------
10 //------------------------------------------------------------------------------
12 const astUtils
= require("./utils/ast-utils");
14 //------------------------------------------------------------------------------
16 //------------------------------------------------------------------------------
23 description
: "enforce that class methods utilize `this`",
25 url
: "https://eslint.org/docs/rules/class-methods-use-this"
37 enforceForClassFields
: {
42 additionalProperties
: false
46 missingThis
: "Expected 'this' to be used by class {{name}}."
50 const config
= Object
.assign({}, context
.options
[0]);
51 const enforceForClassFields
= config
.enforceForClassFields
!== false;
52 const exceptMethods
= new Set(config
.exceptMethods
|| []);
57 * Push `this` used flag initialized with `false` onto the stack.
60 function pushContext() {
65 * Pop `this` used flag from the stack.
66 * @returns {boolean | undefined} `this` used flag
68 function popContext() {
73 * Initializes the current context to false and pushes it onto the stack.
74 * These booleans represent whether 'this' has been used in the context.
78 function enterFunction() {
83 * Check if the node is an instance method
84 * @param {ASTNode} node node to check
85 * @returns {boolean} True if its an instance method
88 function isInstanceMethod(node
) {
90 case "MethodDefinition":
91 return !node
.static && node
.kind
!== "constructor";
92 case "PropertyDefinition":
93 return !node
.static && enforceForClassFields
;
100 * Check if the node is an instance method not excluded by config
101 * @param {ASTNode} node node to check
102 * @returns {boolean} True if it is an instance method, and not excluded by config
105 function isIncludedInstanceMethod(node
) {
106 if (isInstanceMethod(node
)) {
111 const hashIfNeeded
= node
.key
.type
=== "PrivateIdentifier" ? "#" : "";
112 const name
= node
.key
.type
=== "Literal"
113 ? astUtils
.getStaticStringValue(node
.key
)
114 : (node
.key
.name
|| "");
116 return !exceptMethods
.has(hashIfNeeded
+ name
);
122 * Checks if we are leaving a function that is a method, and reports if 'this' has not been used.
123 * Static methods and the constructor are exempt.
124 * Then pops the context off the stack.
125 * @param {ASTNode} node A function node that was entered.
129 function exitFunction(node
) {
130 const methodUsesThis
= popContext();
132 if (isIncludedInstanceMethod(node
.parent
) && !methodUsesThis
) {
135 loc
: astUtils
.getFunctionHeadLoc(node
, context
.getSourceCode()),
136 messageId
: "missingThis",
138 name
: astUtils
.getFunctionNameWithKind(node
)
145 * Mark the current context as having used 'this'.
149 function markThisUsed() {
151 stack
[stack
.length
- 1] = true;
156 FunctionDeclaration
: enterFunction
,
157 "FunctionDeclaration:exit": exitFunction
,
158 FunctionExpression
: enterFunction
,
159 "FunctionExpression:exit": exitFunction
,
162 * Class field value are implicit functions.
164 "PropertyDefinition > *.key:exit": pushContext
,
165 "PropertyDefinition:exit": popContext
,
168 * Class static blocks are implicit functions. They aren't required to use `this`,
169 * but we have to push context so that it captures any use of `this` in the static block
170 * separately from enclosing contexts, because static blocks have their own `this` and it
171 * shouldn't count as used `this` in enclosing contexts.
173 StaticBlock
: pushContext
,
174 "StaticBlock:exit": popContext
,
176 ThisExpression
: markThisUsed
,
179 enforceForClassFields
&& {
180 "PropertyDefinition > ArrowFunctionExpression.value": enterFunction
,
181 "PropertyDefinition > ArrowFunctionExpression.value:exit": exitFunction