Repository: eslint/eslint
File: lib/rules/no-prototype-builtins.js (JavaScript)

Code before:

            if (propName !== null && DISALLOWED_PROPS.has(propName)) {
                context.report({
                    messageId: "prototypeBuildIn",
                    loc: callee.property.loc,
                    data: { prop: propName },
                    node,
                    suggest: [
                        {
                            messageId: "callObjectPrototype",
                            data: { prop: propName },
                            fix(fixer) {

                                /*
                                 * optional member (e.g. a?.hasOwnProperty(b))
                                 * must be rewritten manually
                                 */
                                const isFixable = !callee.optional;
                                const sourceCode = context.sourceCode;
                                const openParenToken = sourceCode.getTokenAfter(
                                    node.callee,
                                    token => token.type === "Punctuator" && token.value === "("
                                );
                                const objectText = sourceCode.text.slice(
                                    context.getSourceCode().getFirstToken(callee.object).range[0],
                                    context.getSourceCode().getLastToken(callee.object).range[1]
                                );
                                const isEmptyParameters = node.arguments.length === 0;
                                const delim = isEmptyParameters ? "" : ", ";
                                const fixes = [
                                    fixer.replaceText(callee, `Object.prototype.${propName}.call`),
                                    fixer.insertTextAfter(openParenToken, objectText + delim)
                                ];

                                return isFixable ? fixes : null;
                            }
                        }
                    ]
                });
            }
        }

        return {
            CallExpression: disallowBuiltIns
        };
    }
};


Review comment (suggestion):
We already have a reference to `sourceCode` above.
```suggestion
                                    sourceCode.getFirstToken(callee.object).range[0],
                                    sourceCode.getLastToken(callee.object).range[1]
```

Code after:
        hasSuggestions: true,

        schema: [],

        messages: {
            prototypeBuildIn: "Do not access Object.prototype method '{{prop}}' from target object.",
            callObjectPrototype: "Call Object.prototype.{{prop}} explicitly."
        }
    },

    create(context) {
        const DISALLOWED_PROPS = new Set([
            "hasOwnProperty",
            "isPrototypeOf",
            "propertyIsEnumerable"
        ]);

        /**
         * Reports if a disallowed property is used in a CallExpression
         * @param {ASTNode} node The CallExpression node.
         * @returns {void}
         */
        function disallowBuiltIns(node) {

            const callee = astUtils.skipChainExpression(node.callee);

            if (callee.type !== "MemberExpression") {
                return;
            }

            const propName = astUtils.getStaticPropertyName(callee);

            if (propName !== null && DISALLOWED_PROPS.has(propName)) {
                context.report({
                    messageId: "prototypeBuildIn",
                    loc: callee.property.loc,
                    data: { prop: propName },
                    node,
                    suggest: [
                        {
                            messageId: "callObjectPrototype",
                            data: { prop: propName },
                            fix(fixer) {
                                const sourceCode = context.sourceCode;

                                /*
                                 * A call after an optional chain (e.g. a?.b.hasOwnProperty(c))
                                 * must be fixed manually because the call can be short-circuited
                                 */
                                if (isAfterOptional(node)) {
                                    return null;