123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- /**
- * @fileoverview Rule to flag wrapping non-iife in parens
- * @author Gyandeep Singh
- */
-
- "use strict";
-
- //------------------------------------------------------------------------------
- // Helpers
- //------------------------------------------------------------------------------
-
- /**
- * Checks whether or not a given node is an `Identifier` node which was named a given name.
- * @param {ASTNode} node - A node to check.
- * @param {string} name - An expected name of the node.
- * @returns {boolean} `true` if the node is an `Identifier` node which was named as expected.
- */
- function isIdentifier(node, name) {
- return node.type === "Identifier" && node.name === name;
- }
-
- /**
- * Checks whether or not a given node is an argument of a specified method call.
- * @param {ASTNode} node - A node to check.
- * @param {number} index - An expected index of the node in arguments.
- * @param {string} object - An expected name of the object of the method.
- * @param {string} property - An expected name of the method.
- * @returns {boolean} `true` if the node is an argument of the specified method call.
- */
- function isArgumentOfMethodCall(node, index, object, property) {
- const parent = node.parent;
-
- return (
- parent.type === "CallExpression" &&
- parent.callee.type === "MemberExpression" &&
- parent.callee.computed === false &&
- isIdentifier(parent.callee.object, object) &&
- isIdentifier(parent.callee.property, property) &&
- parent.arguments[index] === node
- );
- }
-
- /**
- * Checks whether or not a given node is a property descriptor.
- * @param {ASTNode} node - A node to check.
- * @returns {boolean} `true` if the node is a property descriptor.
- */
- function isPropertyDescriptor(node) {
-
- // Object.defineProperty(obj, "foo", {set: ...})
- if (isArgumentOfMethodCall(node, 2, "Object", "defineProperty") ||
- isArgumentOfMethodCall(node, 2, "Reflect", "defineProperty")
- ) {
- return true;
- }
-
- /*
- * Object.defineProperties(obj, {foo: {set: ...}})
- * Object.create(proto, {foo: {set: ...}})
- */
- const grandparent = node.parent.parent;
-
- return grandparent.type === "ObjectExpression" && (
- isArgumentOfMethodCall(grandparent, 1, "Object", "create") ||
- isArgumentOfMethodCall(grandparent, 1, "Object", "defineProperties")
- );
- }
-
- //------------------------------------------------------------------------------
- // Rule Definition
- //------------------------------------------------------------------------------
-
- module.exports = {
- meta: {
- type: "suggestion",
-
- docs: {
- description: "enforce getter and setter pairs in objects",
- category: "Best Practices",
- recommended: false,
- url: "https://eslint.org/docs/rules/accessor-pairs"
- },
-
- schema: [{
- type: "object",
- properties: {
- getWithoutSet: {
- type: "boolean"
- },
- setWithoutGet: {
- type: "boolean"
- }
- },
- additionalProperties: false
- }],
-
- messages: {
- getter: "Getter is not present.",
- setter: "Setter is not present."
- }
- },
- create(context) {
- const config = context.options[0] || {};
- const checkGetWithoutSet = config.getWithoutSet === true;
- const checkSetWithoutGet = config.setWithoutGet !== false;
-
- /**
- * Checks a object expression to see if it has setter and getter both present or none.
- * @param {ASTNode} node The node to check.
- * @returns {void}
- * @private
- */
- function checkLonelySetGet(node) {
- let isSetPresent = false;
- let isGetPresent = false;
- const isDescriptor = isPropertyDescriptor(node);
-
- for (let i = 0, end = node.properties.length; i < end; i++) {
- const property = node.properties[i];
-
- let propToCheck = "";
-
- if (property.kind === "init") {
- if (isDescriptor && !property.computed) {
- propToCheck = property.key.name;
- }
- } else {
- propToCheck = property.kind;
- }
-
- switch (propToCheck) {
- case "set":
- isSetPresent = true;
- break;
-
- case "get":
- isGetPresent = true;
- break;
-
- default:
-
- // Do nothing
- }
-
- if (isSetPresent && isGetPresent) {
- break;
- }
- }
-
- if (checkSetWithoutGet && isSetPresent && !isGetPresent) {
- context.report({ node, messageId: "getter" });
- } else if (checkGetWithoutSet && isGetPresent && !isSetPresent) {
- context.report({ node, messageId: "setter" });
- }
- }
-
- return {
- ObjectExpression(node) {
- if (checkSetWithoutGet || checkGetWithoutSet) {
- checkLonelySetGet(node);
- }
- }
- };
- }
- };
|