prefer-reflect.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /**
  2. * @fileoverview Rule to suggest using "Reflect" api over Function/Object methods
  3. * @author Keith Cirkel <http://keithcirkel.co.uk>
  4. * @deprecated in ESLint v3.9.0
  5. */
  6. "use strict";
  7. //------------------------------------------------------------------------------
  8. // Rule Definition
  9. //------------------------------------------------------------------------------
  10. module.exports = {
  11. meta: {
  12. docs: {
  13. description: "require `Reflect` methods where applicable",
  14. category: "ECMAScript 6",
  15. recommended: false,
  16. replacedBy: [],
  17. url: "https://eslint.org/docs/rules/prefer-reflect"
  18. },
  19. deprecated: true,
  20. schema: [
  21. {
  22. type: "object",
  23. properties: {
  24. exceptions: {
  25. type: "array",
  26. items: {
  27. enum: [
  28. "apply",
  29. "call",
  30. "delete",
  31. "defineProperty",
  32. "getOwnPropertyDescriptor",
  33. "getPrototypeOf",
  34. "setPrototypeOf",
  35. "isExtensible",
  36. "getOwnPropertyNames",
  37. "preventExtensions"
  38. ]
  39. },
  40. uniqueItems: true
  41. }
  42. },
  43. additionalProperties: false
  44. }
  45. ]
  46. },
  47. create(context) {
  48. const existingNames = {
  49. apply: "Function.prototype.apply",
  50. call: "Function.prototype.call",
  51. defineProperty: "Object.defineProperty",
  52. getOwnPropertyDescriptor: "Object.getOwnPropertyDescriptor",
  53. getPrototypeOf: "Object.getPrototypeOf",
  54. setPrototypeOf: "Object.setPrototypeOf",
  55. isExtensible: "Object.isExtensible",
  56. getOwnPropertyNames: "Object.getOwnPropertyNames",
  57. preventExtensions: "Object.preventExtensions"
  58. };
  59. const reflectSubsitutes = {
  60. apply: "Reflect.apply",
  61. call: "Reflect.apply",
  62. defineProperty: "Reflect.defineProperty",
  63. getOwnPropertyDescriptor: "Reflect.getOwnPropertyDescriptor",
  64. getPrototypeOf: "Reflect.getPrototypeOf",
  65. setPrototypeOf: "Reflect.setPrototypeOf",
  66. isExtensible: "Reflect.isExtensible",
  67. getOwnPropertyNames: "Reflect.getOwnPropertyNames",
  68. preventExtensions: "Reflect.preventExtensions"
  69. };
  70. const exceptions = (context.options[0] || {}).exceptions || [];
  71. /**
  72. * Reports the Reflect violation based on the `existing` and `substitute`
  73. * @param {Object} node The node that violates the rule.
  74. * @param {string} existing The existing method name that has been used.
  75. * @param {string} substitute The Reflect substitute that should be used.
  76. * @returns {void}
  77. */
  78. function report(node, existing, substitute) {
  79. context.report({
  80. node,
  81. message: "Avoid using {{existing}}, instead use {{substitute}}.",
  82. data: {
  83. existing,
  84. substitute
  85. }
  86. });
  87. }
  88. return {
  89. CallExpression(node) {
  90. const methodName = (node.callee.property || {}).name;
  91. const isReflectCall = (node.callee.object || {}).name === "Reflect";
  92. const hasReflectSubsitute = reflectSubsitutes.hasOwnProperty(methodName);
  93. const userConfiguredException = exceptions.indexOf(methodName) !== -1;
  94. if (hasReflectSubsitute && !isReflectCall && !userConfiguredException) {
  95. report(node, existingNames[methodName], reflectSubsitutes[methodName]);
  96. }
  97. },
  98. UnaryExpression(node) {
  99. const isDeleteOperator = node.operator === "delete";
  100. const targetsIdentifier = node.argument.type === "Identifier";
  101. const userConfiguredException = exceptions.indexOf("delete") !== -1;
  102. if (isDeleteOperator && !targetsIdentifier && !userConfiguredException) {
  103. report(node, "the delete keyword", "Reflect.deleteProperty");
  104. }
  105. }
  106. };
  107. }
  108. };