Blame view

node_modules/eslint/lib/rules/no-dupe-class-members.js 3.41 KB
f7563de62   Palak Handa   first commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
  /**
   * @fileoverview A rule to disallow duplicate name in class members.
   * @author Toru Nagashima
   */
  
  "use strict";
  
  //------------------------------------------------------------------------------
  // Rule Definition
  //------------------------------------------------------------------------------
  
  module.exports = {
      meta: {
          docs: {
              description: "disallow duplicate class members",
              category: "ECMAScript 6",
              recommended: true
          },
  
          schema: []
      },
  
      create(context) {
          let stack = [];
  
          /**
           * Gets state of a given member name.
           * @param {string} name - A name of a member.
           * @param {boolean} isStatic - A flag which specifies that is a static member.
           * @returns {Object} A state of a given member name.
           *   - retv.init {boolean} A flag which shows the name is declared as normal member.
           *   - retv.get {boolean} A flag which shows the name is declared as getter.
           *   - retv.set {boolean} A flag which shows the name is declared as setter.
           */
          function getState(name, isStatic) {
              const stateMap = stack[stack.length - 1];
              const key = `$${name}`; // to avoid "__proto__".
  
              if (!stateMap[key]) {
                  stateMap[key] = {
                      nonStatic: { init: false, get: false, set: false },
                      static: { init: false, get: false, set: false }
                  };
              }
  
              return stateMap[key][isStatic ? "static" : "nonStatic"];
          }
  
          /**
           * Gets the name text of a given node.
           *
           * @param {ASTNode} node - A node to get the name.
           * @returns {string} The name text of the node.
           */
          function getName(node) {
              switch (node.type) {
                  case "Identifier": return node.name;
                  case "Literal": return String(node.value);
  
                  /* istanbul ignore next: syntax error */
                  default: return "";
              }
          }
  
          return {
  
              // Initializes the stack of state of member declarations.
              Program() {
                  stack = [];
              },
  
              // Initializes state of member declarations for the class.
              ClassBody() {
                  stack.push(Object.create(null));
              },
  
              // Disposes the state for the class.
              "ClassBody:exit"() {
                  stack.pop();
              },
  
              // Reports the node if its name has been declared already.
              MethodDefinition(node) {
                  if (node.computed) {
                      return;
                  }
  
                  const name = getName(node.key);
                  const state = getState(name, node.static);
                  let isDuplicate = false;
  
                  if (node.kind === "get") {
                      isDuplicate = (state.init || state.get);
                      state.get = true;
                  } else if (node.kind === "set") {
                      isDuplicate = (state.init || state.set);
                      state.set = true;
                  } else {
                      isDuplicate = (state.init || state.get || state.set);
                      state.init = true;
                  }
  
                  if (isDuplicate) {
                      context.report({ node, message: "Duplicate name '{{name}}'.", data: { name } });
                  }
              }
          };
      }
  };