项目原始demo,不改动
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
Den här utvecklingskatalogen är arkiverad. Du kan se filer och klona katalogen, men inte öppna ärenden eller genomföra push- eller pull-förfrågningar.
 
 
 
 

175 rader
6.4 KiB

  1. /**
  2. * @fileoverview Rule to disallow certain object properties
  3. * @author Will Klein & Eli White
  4. */
  5. "use strict";
  6. const astUtils = require("../ast-utils");
  7. //------------------------------------------------------------------------------
  8. // Rule Definition
  9. //------------------------------------------------------------------------------
  10. module.exports = {
  11. meta: {
  12. docs: {
  13. description: "disallow certain properties on certain objects",
  14. category: "Best Practices",
  15. recommended: false,
  16. url: "https://eslint.org/docs/rules/no-restricted-properties"
  17. },
  18. schema: {
  19. type: "array",
  20. items: {
  21. anyOf: [ // `object` and `property` are both optional, but at least one of them must be provided.
  22. {
  23. type: "object",
  24. properties: {
  25. object: {
  26. type: "string"
  27. },
  28. property: {
  29. type: "string"
  30. },
  31. message: {
  32. type: "string"
  33. }
  34. },
  35. additionalProperties: false,
  36. required: ["object"]
  37. },
  38. {
  39. type: "object",
  40. properties: {
  41. object: {
  42. type: "string"
  43. },
  44. property: {
  45. type: "string"
  46. },
  47. message: {
  48. type: "string"
  49. }
  50. },
  51. additionalProperties: false,
  52. required: ["property"]
  53. }
  54. ]
  55. },
  56. uniqueItems: true
  57. }
  58. },
  59. create(context) {
  60. const restrictedCalls = context.options;
  61. if (restrictedCalls.length === 0) {
  62. return {};
  63. }
  64. const restrictedProperties = new Map();
  65. const globallyRestrictedObjects = new Map();
  66. const globallyRestrictedProperties = new Map();
  67. restrictedCalls.forEach(option => {
  68. const objectName = option.object;
  69. const propertyName = option.property;
  70. if (typeof objectName === "undefined") {
  71. globallyRestrictedProperties.set(propertyName, { message: option.message });
  72. } else if (typeof propertyName === "undefined") {
  73. globallyRestrictedObjects.set(objectName, { message: option.message });
  74. } else {
  75. if (!restrictedProperties.has(objectName)) {
  76. restrictedProperties.set(objectName, new Map());
  77. }
  78. restrictedProperties.get(objectName).set(propertyName, {
  79. message: option.message
  80. });
  81. }
  82. });
  83. /**
  84. * Checks to see whether a property access is restricted, and reports it if so.
  85. * @param {ASTNode} node The node to report
  86. * @param {string} objectName The name of the object
  87. * @param {string} propertyName The name of the property
  88. * @returns {undefined}
  89. */
  90. function checkPropertyAccess(node, objectName, propertyName) {
  91. if (propertyName === null) {
  92. return;
  93. }
  94. const matchedObject = restrictedProperties.get(objectName);
  95. const matchedObjectProperty = matchedObject ? matchedObject.get(propertyName) : globallyRestrictedObjects.get(objectName);
  96. const globalMatchedProperty = globallyRestrictedProperties.get(propertyName);
  97. if (matchedObjectProperty) {
  98. const message = matchedObjectProperty.message ? ` ${matchedObjectProperty.message}` : "";
  99. context.report({
  100. node,
  101. // eslint-disable-next-line eslint-plugin/report-message-format
  102. message: "'{{objectName}}.{{propertyName}}' is restricted from being used.{{message}}",
  103. data: {
  104. objectName,
  105. propertyName,
  106. message
  107. }
  108. });
  109. } else if (globalMatchedProperty) {
  110. const message = globalMatchedProperty.message ? ` ${globalMatchedProperty.message}` : "";
  111. context.report({
  112. node,
  113. // eslint-disable-next-line eslint-plugin/report-message-format
  114. message: "'{{propertyName}}' is restricted from being used.{{message}}",
  115. data: {
  116. propertyName,
  117. message
  118. }
  119. });
  120. }
  121. }
  122. /**
  123. * Checks property accesses in a destructuring assignment expression, e.g. `var foo; ({foo} = bar);`
  124. * @param {ASTNode} node An AssignmentExpression or AssignmentPattern node
  125. * @returns {undefined}
  126. */
  127. function checkDestructuringAssignment(node) {
  128. if (node.right.type === "Identifier") {
  129. const objectName = node.right.name;
  130. if (node.left.type === "ObjectPattern") {
  131. node.left.properties.forEach(property => {
  132. checkPropertyAccess(node.left, objectName, astUtils.getStaticPropertyName(property));
  133. });
  134. }
  135. }
  136. }
  137. return {
  138. MemberExpression(node) {
  139. checkPropertyAccess(node, node.object && node.object.name, astUtils.getStaticPropertyName(node));
  140. },
  141. VariableDeclarator(node) {
  142. if (node.init && node.init.type === "Identifier") {
  143. const objectName = node.init.name;
  144. if (node.id.type === "ObjectPattern") {
  145. node.id.properties.forEach(property => {
  146. checkPropertyAccess(node.id, objectName, astUtils.getStaticPropertyName(property));
  147. });
  148. }
  149. }
  150. },
  151. AssignmentExpression: checkDestructuringAssignment,
  152. AssignmentPattern: checkDestructuringAssignment
  153. };
  154. }
  155. };