We have been stalled on ESLint 3.8.0 for some time. Current ESLint is 3.13.0. We have been unable to upgrade because of more aggressive reporting on some rules, including indentation. ESLint configuration options and bugfixes are now such that we can reasonably upgrade. PR-URL: https://github.com/nodejs/node/pull/10561 Reviewed-By: Teddy Katz <teddy.katz@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
109 lines
3.4 KiB
JavaScript
109 lines
3.4 KiB
JavaScript
/**
|
|
* @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 } });
|
|
}
|
|
}
|
|
};
|
|
}
|
|
};
|