/**
							 | 
						|
								 * @fileoverview Prefers Object.hasOwn() instead of Object.prototype.hasOwnProperty.call()
							 | 
						|
								 * @author Nitin Kumar
							 | 
						|
								 * @author Gautam Arora
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								"use strict";
							 | 
						|
								
							 | 
						|
								//------------------------------------------------------------------------------
							 | 
						|
								// Requirements
							 | 
						|
								//------------------------------------------------------------------------------
							 | 
						|
								
							 | 
						|
								const astUtils = require("./utils/ast-utils");
							 | 
						|
								
							 | 
						|
								//------------------------------------------------------------------------------
							 | 
						|
								// Helpers
							 | 
						|
								//------------------------------------------------------------------------------
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Checks if the given node is considered to be an access to a property of `Object.prototype`.
							 | 
						|
								 * @param {ASTNode} node `MemberExpression` node to evaluate.
							 | 
						|
								 * @returns {boolean} `true` if `node.object` is `Object`, `Object.prototype`, or `{}` (empty 'ObjectExpression' node).
							 | 
						|
								 */
							 | 
						|
								function hasLeftHandObject(node) {
							 | 
						|
								
							 | 
						|
								    /*
							 | 
						|
								     * ({}).hasOwnProperty.call(obj, prop) - `true`
							 | 
						|
								     * ({ foo }.hasOwnProperty.call(obj, prop)) - `false`, object literal should be empty
							 | 
						|
								     */
							 | 
						|
								    if (node.object.type === "ObjectExpression" && node.object.properties.length === 0) {
							 | 
						|
								        return true;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    const objectNodeToCheck = node.object.type === "MemberExpression" && astUtils.getStaticPropertyName(node.object) === "prototype" ? node.object.object : node.object;
							 | 
						|
								
							 | 
						|
								    if (objectNodeToCheck.type === "Identifier" && objectNodeToCheck.name === "Object") {
							 | 
						|
								        return true;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    return false;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								//------------------------------------------------------------------------------
							 | 
						|
								// Rule Definition
							 | 
						|
								//------------------------------------------------------------------------------
							 | 
						|
								
							 | 
						|
								/** @type {import('../shared/types').Rule} */
							 | 
						|
								module.exports = {
							 | 
						|
								    meta: {
							 | 
						|
								        type: "suggestion",
							 | 
						|
								        docs: {
							 | 
						|
								            description:
							 | 
						|
								                "Disallow use of `Object.prototype.hasOwnProperty.call()` and prefer use of `Object.hasOwn()`",
							 | 
						|
								            recommended: false,
							 | 
						|
								            url: "https://eslint.org/docs/latest/rules/prefer-object-has-own"
							 | 
						|
								        },
							 | 
						|
								        schema: [],
							 | 
						|
								        messages: {
							 | 
						|
								            useHasOwn: "Use 'Object.hasOwn()' instead of 'Object.prototype.hasOwnProperty.call()'."
							 | 
						|
								        },
							 | 
						|
								        fixable: "code"
							 | 
						|
								    },
							 | 
						|
								    create(context) {
							 | 
						|
								
							 | 
						|
								        const sourceCode = context.sourceCode;
							 | 
						|
								
							 | 
						|
								        return {
							 | 
						|
								            CallExpression(node) {
							 | 
						|
								                if (!(node.callee.type === "MemberExpression" && node.callee.object.type === "MemberExpression")) {
							 | 
						|
								                    return;
							 | 
						|
								                }
							 | 
						|
								
							 | 
						|
								                const calleePropertyName = astUtils.getStaticPropertyName(node.callee);
							 | 
						|
								                const objectPropertyName = astUtils.getStaticPropertyName(node.callee.object);
							 | 
						|
								                const isObject = hasLeftHandObject(node.callee.object);
							 | 
						|
								
							 | 
						|
								                // check `Object` scope
							 | 
						|
								                const scope = sourceCode.getScope(node);
							 | 
						|
								                const variable = astUtils.getVariableByName(scope, "Object");
							 | 
						|
								
							 | 
						|
								                if (
							 | 
						|
								                    calleePropertyName === "call" &&
							 | 
						|
								                    objectPropertyName === "hasOwnProperty" &&
							 | 
						|
								                    isObject &&
							 | 
						|
								                    variable && variable.scope.type === "global"
							 | 
						|
								                ) {
							 | 
						|
								                    context.report({
							 | 
						|
								                        node,
							 | 
						|
								                        messageId: "useHasOwn",
							 | 
						|
								                        fix(fixer) {
							 | 
						|
								
							 | 
						|
								                            if (sourceCode.getCommentsInside(node.callee).length > 0) {
							 | 
						|
								                                return null;
							 | 
						|
								                            }
							 | 
						|
								
							 | 
						|
								                            const tokenJustBeforeNode = sourceCode.getTokenBefore(node.callee, { includeComments: true });
							 | 
						|
								
							 | 
						|
								                            // for https://github.com/eslint/eslint/pull/15346#issuecomment-991417335
							 | 
						|
								                            if (
							 | 
						|
								                                tokenJustBeforeNode &&
							 | 
						|
								                                tokenJustBeforeNode.range[1] === node.callee.range[0] &&
							 | 
						|
								                                !astUtils.canTokensBeAdjacent(tokenJustBeforeNode, "Object.hasOwn")
							 | 
						|
								                            ) {
							 | 
						|
								                                return fixer.replaceText(node.callee, " Object.hasOwn");
							 | 
						|
								                            }
							 | 
						|
								
							 | 
						|
								                            return fixer.replaceText(node.callee, "Object.hasOwn");
							 | 
						|
								                        }
							 | 
						|
								                    });
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								        };
							 | 
						|
								    }
							 | 
						|
								};
							 |