Repository: eslint/eslint
File: lib/rules/getter-return.js (JavaScript)

Code before:

        /**
         * Checks whether a node means a getter function.
         * @param {ASTNode} node a node to check.
         * @returns {boolean} if node means a getter, return true; else return false.
         */
        function isGetter(node) {
            const parent = node.parent;

            if (TARGET_NODE_TYPE.test(node.type) && node.body.type === "BlockStatement") {
                if (parent.kind === "get") {
                    return true;
                }
                if (parent.type === "Property" && astUtils.getStaticPropertyName(parent) === "get" && parent.parent.type === "ObjectExpression") {

                    // Object.defineProperty()
                    if (parent.parent.parent.type === "CallExpression" &&
                        astUtils.getStaticPropertyName(parent.parent.parent.callee) === "defineProperty") {
                        return true;
                    }

                    // Object.defineProperties() or Object.create()
                    if (parent.parent.parent.type === "Property" &&
                        parent.parent.parent.parent.type === "ObjectExpression" &&
                        parent.parent.parent.parent.parent.type === "CallExpression") {
                        const calleePropName = astUtils.getStaticPropertyName(parent.parent.parent.parent.parent.callee);

                        return calleePropName === "defineProperties" || calleePropName === "create";
                    }
                }
            }
            return false;
        }
        return {

            // Stacks this function's information.
            onCodePathStart(codePath, node) {
                funcInfo = {
                    upper: funcInfo,
                    codePath,
                    hasReturn: false,
                    shouldCheck: isGetter(node),
                    node
                };
            },

            // Pops this function's information.
            onCodePathEnd() {
                funcInfo = funcInfo.upper;
            },


Review comment (suggestion):
It seems we forgot to check if `callee.object` is `Object` identifier.

```js
foo.create(null, {
    bar: { get() {} } // false positive
});
```

This is an inherited problem (the same happens with `foo.defineProperty` and `foo.defineProperties`), but since it will now generate even more false positives, and `create` is a common name, it would be good to include that fix in this change.

Code after:

        /**
         * Checks whether a node means a getter function.
         * @param {ASTNode} node a node to check.
         * @returns {boolean} if node means a getter, return true; else return false.
         */
        function isGetter(node) {
            const parent = node.parent;

            if (TARGET_NODE_TYPE.test(node.type) && node.body.type === "BlockStatement") {
                if (parent.kind === "get") {
                    return true;
                }
                if (parent.type === "Property" && astUtils.getStaticPropertyName(parent) === "get" && parent.parent.type === "ObjectExpression") {

                    // Object.defineProperty() or Reflect.defineProperty()
                    if (parent.parent.parent.type === "CallExpression") {
                        const callNode = parent.parent.parent.callee;

                        if (astUtils.isSpecificMemberAccess(callNode, "Object", "defineProperty") ||
                            astUtils.isSpecificMemberAccess(callNode, "Reflect", "defineProperty")) {
                            return true;
                        }
                    }

                    // Object.defineProperties() or Object.create()
                    if (parent.parent.parent.type === "Property" &&
                        parent.parent.parent.parent.type === "ObjectExpression" &&
                        parent.parent.parent.parent.parent.type === "CallExpression") {
                        const callNode = parent.parent.parent.parent.parent.callee;

                        return astUtils.isSpecificMemberAccess(callNode, "Object", "defineProperties") ||
                               astUtils.isSpecificMemberAccess(callNode, "Object", "create");
                    }
                }
            }
            return false;
        }
        return {

            // Stacks this function's information.
            onCodePathStart(codePath, node) {
                funcInfo = {
                    upper: funcInfo,
                    codePath,
                    hasReturn: false,
                    shouldCheck: isGetter(node),
                    node
                };
            },