UNPKG

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