From f13d4a6cf7c7ff6160be7426fc6fe02e3e37a0b7 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Tue, 14 Dec 2021 21:44:30 +0530 Subject: [PATCH] fix: improve autofix of `prefer-object-has-own` (#15419) * fix: improve autofix of `prefer-object-has-own` * fix: cover more cases * test: add more cases * test: add more test cases * fix: avoid unnecessary space in autofix output * refactor: code * refactor: apply suggestion --- lib/rules/prefer-object-has-own.js | 15 +++ tests/lib/rules/prefer-object-has-own.js | 112 +++++++++++++++++++++++ 2 files changed, 127 insertions(+) diff --git a/lib/rules/prefer-object-has-own.js b/lib/rules/prefer-object-has-own.js index dd21e95d47e..19abdb31565 100644 --- a/lib/rules/prefer-object-has-own.js +++ b/lib/rules/prefer-object-has-own.js @@ -12,6 +12,10 @@ 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. @@ -87,6 +91,17 @@ module.exports = { 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"); } }); diff --git a/tests/lib/rules/prefer-object-has-own.js b/tests/lib/rules/prefer-object-has-own.js index a34cf774555..d58f7f5c211 100644 --- a/tests/lib/rules/prefer-object-has-own.js +++ b/tests/lib/rules/prefer-object-has-own.js @@ -224,6 +224,17 @@ ruleTester.run("prefer-object-has-own", rule, { endColumn: 61 }] }, + { + code: "const hasProperty={}.hasOwnProperty.call(object, property);", + output: "const hasProperty=Object.hasOwn(object, property);", + errors: [{ + messageId: "useHasOwn", + line: 1, + column: 19, + endLine: 1, + endColumn: 59 + }] + }, { code: "const hasProperty = (( {}.hasOwnProperty.call(object, property) ));", output: "const hasProperty = (( Object.hasOwn(object, property) ));", @@ -279,6 +290,107 @@ ruleTester.run("prefer-object-has-own", rule, { endColumn: 63 }] }, + + // https://github.com/eslint/eslint/pull/15346#issuecomment-991417335 + { + code: "function foo(){return{}.hasOwnProperty.call(object, property)}", + output: "function foo(){return Object.hasOwn(object, property)}", + errors: [{ + messageId: "useHasOwn", + line: 1, + column: 22, + endLine: 1, + endColumn: 62 + }] + }, + { + code: "function foo(){return/*comment*/{}.hasOwnProperty.call(object, property)}", + output: "function foo(){return/*comment*/Object.hasOwn(object, property)}", + errors: [{ + messageId: "useHasOwn", + line: 1, + column: 33, + endLine: 1, + endColumn: 73 + }] + }, + { + code: "async function foo(){return await{}.hasOwnProperty.call(object, property)}", + output: "async function foo(){return await Object.hasOwn(object, property)}", + errors: [{ + messageId: "useHasOwn", + line: 1, + column: 34, + endLine: 1, + endColumn: 74 + }] + }, + { + code: "async function foo(){return await/*comment*/{}.hasOwnProperty.call(object, property)}", + output: "async function foo(){return await/*comment*/Object.hasOwn(object, property)}", + errors: [{ + messageId: "useHasOwn", + line: 1, + column: 45, + endLine: 1, + endColumn: 85 + }] + }, + { + code: "for (const x of{}.hasOwnProperty.call(object, property).toString());", + output: "for (const x of Object.hasOwn(object, property).toString());", + errors: [{ + messageId: "useHasOwn", + line: 1, + column: 16, + endLine: 1, + endColumn: 56 + }] + }, + { + code: "for (const x of/*comment*/{}.hasOwnProperty.call(object, property).toString());", + output: "for (const x of/*comment*/Object.hasOwn(object, property).toString());", + errors: [{ + messageId: "useHasOwn", + line: 1, + column: 27, + endLine: 1, + endColumn: 67 + }] + }, + { + code: "for (const x in{}.hasOwnProperty.call(object, property).toString());", + output: "for (const x in Object.hasOwn(object, property).toString());", + errors: [{ + messageId: "useHasOwn", + line: 1, + column: 16, + endLine: 1, + endColumn: 56 + }] + }, + { + code: "for (const x in/*comment*/{}.hasOwnProperty.call(object, property).toString());", + output: "for (const x in/*comment*/Object.hasOwn(object, property).toString());", + errors: [{ + messageId: "useHasOwn", + line: 1, + column: 27, + endLine: 1, + endColumn: 67 + }] + }, + { + code: "function foo(){return({}.hasOwnProperty.call)(object, property)}", + output: "function foo(){return(Object.hasOwn)(object, property)}", + errors: [{ + messageId: "useHasOwn", + line: 1, + column: 22, + endLine: 1, + endColumn: 64 + }] + }, { code: "Object['prototype']['hasOwnProperty']['call'](object, property);", output: "Object.hasOwn(object, property);",