项目原始demo,不改动
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
此仓库已存档。您可以查看文件和克隆,但不能推送或创建工单/合并请求。
 
 
 
 

141 行
3.8 KiB

  1. /**
  2. * @fileoverview Rule to flag use of duplicate keys in an object.
  3. * @author Ian Christian Myers
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Requirements
  8. //------------------------------------------------------------------------------
  9. const astUtils = require("../ast-utils");
  10. //------------------------------------------------------------------------------
  11. // Helpers
  12. //------------------------------------------------------------------------------
  13. const GET_KIND = /^(?:init|get)$/;
  14. const SET_KIND = /^(?:init|set)$/;
  15. /**
  16. * The class which stores properties' information of an object.
  17. */
  18. class ObjectInfo {
  19. /**
  20. * @param {ObjectInfo|null} upper - The information of the outer object.
  21. * @param {ASTNode} node - The ObjectExpression node of this information.
  22. */
  23. constructor(upper, node) {
  24. this.upper = upper;
  25. this.node = node;
  26. this.properties = new Map();
  27. }
  28. /**
  29. * Gets the information of the given Property node.
  30. * @param {ASTNode} node - The Property node to get.
  31. * @returns {{get: boolean, set: boolean}} The information of the property.
  32. */
  33. getPropertyInfo(node) {
  34. const name = astUtils.getStaticPropertyName(node);
  35. if (!this.properties.has(name)) {
  36. this.properties.set(name, { get: false, set: false });
  37. }
  38. return this.properties.get(name);
  39. }
  40. /**
  41. * Checks whether the given property has been defined already or not.
  42. * @param {ASTNode} node - The Property node to check.
  43. * @returns {boolean} `true` if the property has been defined.
  44. */
  45. isPropertyDefined(node) {
  46. const entry = this.getPropertyInfo(node);
  47. return (
  48. (GET_KIND.test(node.kind) && entry.get) ||
  49. (SET_KIND.test(node.kind) && entry.set)
  50. );
  51. }
  52. /**
  53. * Defines the given property.
  54. * @param {ASTNode} node - The Property node to define.
  55. * @returns {void}
  56. */
  57. defineProperty(node) {
  58. const entry = this.getPropertyInfo(node);
  59. if (GET_KIND.test(node.kind)) {
  60. entry.get = true;
  61. }
  62. if (SET_KIND.test(node.kind)) {
  63. entry.set = true;
  64. }
  65. }
  66. }
  67. //------------------------------------------------------------------------------
  68. // Rule Definition
  69. //------------------------------------------------------------------------------
  70. module.exports = {
  71. meta: {
  72. docs: {
  73. description: "disallow duplicate keys in object literals",
  74. category: "Possible Errors",
  75. recommended: true,
  76. url: "https://eslint.org/docs/rules/no-dupe-keys"
  77. },
  78. schema: [],
  79. messages: {
  80. unexpected: "Duplicate key '{{name}}'."
  81. }
  82. },
  83. create(context) {
  84. let info = null;
  85. return {
  86. ObjectExpression(node) {
  87. info = new ObjectInfo(info, node);
  88. },
  89. "ObjectExpression:exit"() {
  90. info = info.upper;
  91. },
  92. Property(node) {
  93. const name = astUtils.getStaticPropertyName(node);
  94. // Skip destructuring.
  95. if (node.parent.type !== "ObjectExpression") {
  96. return;
  97. }
  98. // Skip if the name is not static.
  99. if (!name) {
  100. return;
  101. }
  102. // Reports if the name is defined already.
  103. if (info.isPropertyDefined(node)) {
  104. context.report({
  105. node: info.node,
  106. loc: node.key.loc,
  107. messageId: "unexpected",
  108. data: { name }
  109. });
  110. }
  111. // Update info.
  112. info.defineProperty(node);
  113. }
  114. };
  115. }
  116. };