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

Code before:
                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) {

                                /*
                                 * a call after an optional chain (e.g. a?.b.hasOwnProperty(c))
                                 * must be rewritten manually because the call can be short-circuited
                                 */
                                const isFixable = !isAfterOptional(node);
                                const sourceCode = context.sourceCode;
                                const openParenToken = sourceCode.getTokenAfter(
                                    node.callee,
                                    token => token.type === "Punctuator" && token.value === "("
                                );
                                const objectText = sourceCode.text.slice(
                                    sourceCode.getFirstToken(callee.object).range[0],
                                    sourceCode.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):
```suggestion
                                    astUtils.isOpeningParenToken
```

Code after:

            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;
                                }

                                /*
                                 * A call on a ChainExpression (e.g. (a?.hasOwnProperty)(c)) will trigger
                                 * no-unsafe-optional-chaining which should be fixed before this suggestion
                                 */
                                if (node.callee.type === "ChainExpression") {
                                    return null;
                                }

                                const objectVariable = astUtils.getVariableByName(sourceCode.getScope(node), "Object");

                                /*
                                 * We can't use Object if the global Object was shadowed,
                                 * or Object does not exist in the global scope for some reason
                                 */
                                if (!objectVariable || objectVariable.scope.type !== "global" || objectVariable.defs.length > 0) {
                                    return null;
                                }

                                let objectText = sourceCode.getText(callee.object);

                                if (astUtils.getPrecedence(callee.object) <= astUtils.getPrecedence({ type: "SequenceExpression" })) {
                                    objectText = `(${objectText})`;
                                }

                                const openParenToken = sourceCode.getTokenAfter(
                                    node.callee,
                                    astUtils.isOpeningParenToken