]> git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/rules/prefer-object-has-own.js
import 8.41.0 source
[pve-eslint.git] / eslint / lib / rules / prefer-object-has-own.js
1 /**
2 * @fileoverview Prefers Object.hasOwn() instead of Object.prototype.hasOwnProperty.call()
3 * @author Nitin Kumar
4 * @author Gautam Arora
5 */
6
7 "use strict";
8
9 //------------------------------------------------------------------------------
10 // Requirements
11 //------------------------------------------------------------------------------
12
13 const astUtils = require("./utils/ast-utils");
14
15 //------------------------------------------------------------------------------
16 // Helpers
17 //------------------------------------------------------------------------------
18
19 /**
20 * Checks if the given node is considered to be an access to a property of `Object.prototype`.
21 * @param {ASTNode} node `MemberExpression` node to evaluate.
22 * @returns {boolean} `true` if `node.object` is `Object`, `Object.prototype`, or `{}` (empty 'ObjectExpression' node).
23 */
24 function hasLeftHandObject(node) {
25
26 /*
27 * ({}).hasOwnProperty.call(obj, prop) - `true`
28 * ({ foo }.hasOwnProperty.call(obj, prop)) - `false`, object literal should be empty
29 */
30 if (node.object.type === "ObjectExpression" && node.object.properties.length === 0) {
31 return true;
32 }
33
34 const objectNodeToCheck = node.object.type === "MemberExpression" && astUtils.getStaticPropertyName(node.object) === "prototype" ? node.object.object : node.object;
35
36 if (objectNodeToCheck.type === "Identifier" && objectNodeToCheck.name === "Object") {
37 return true;
38 }
39
40 return false;
41 }
42
43 //------------------------------------------------------------------------------
44 // Rule Definition
45 //------------------------------------------------------------------------------
46
47 /** @type {import('../shared/types').Rule} */
48 module.exports = {
49 meta: {
50 type: "suggestion",
51 docs: {
52 description:
53 "Disallow use of `Object.prototype.hasOwnProperty.call()` and prefer use of `Object.hasOwn()`",
54 recommended: false,
55 url: "https://eslint.org/docs/latest/rules/prefer-object-has-own"
56 },
57 schema: [],
58 messages: {
59 useHasOwn: "Use 'Object.hasOwn()' instead of 'Object.prototype.hasOwnProperty.call()'."
60 },
61 fixable: "code"
62 },
63 create(context) {
64
65 const sourceCode = context.sourceCode;
66
67 return {
68 CallExpression(node) {
69 if (!(node.callee.type === "MemberExpression" && node.callee.object.type === "MemberExpression")) {
70 return;
71 }
72
73 const calleePropertyName = astUtils.getStaticPropertyName(node.callee);
74 const objectPropertyName = astUtils.getStaticPropertyName(node.callee.object);
75 const isObject = hasLeftHandObject(node.callee.object);
76
77 // check `Object` scope
78 const scope = sourceCode.getScope(node);
79 const variable = astUtils.getVariableByName(scope, "Object");
80
81 if (
82 calleePropertyName === "call" &&
83 objectPropertyName === "hasOwnProperty" &&
84 isObject &&
85 variable && variable.scope.type === "global"
86 ) {
87 context.report({
88 node,
89 messageId: "useHasOwn",
90 fix(fixer) {
91
92 if (sourceCode.getCommentsInside(node.callee).length > 0) {
93 return null;
94 }
95
96 const tokenJustBeforeNode = sourceCode.getTokenBefore(node.callee, { includeComments: true });
97
98 // for https://github.com/eslint/eslint/pull/15346#issuecomment-991417335
99 if (
100 tokenJustBeforeNode &&
101 tokenJustBeforeNode.range[1] === node.callee.range[0] &&
102 !astUtils.canTokensBeAdjacent(tokenJustBeforeNode, "Object.hasOwn")
103 ) {
104 return fixer.replaceText(node.callee, " Object.hasOwn");
105 }
106
107 return fixer.replaceText(node.callee, "Object.hasOwn");
108 }
109 });
110 }
111 }
112 };
113 }
114 };