Skip to content

Commit

Permalink
Add support for class properties in no-dupe-class-members
Browse files Browse the repository at this point in the history
Fixes: eslint/eslint#7534

Stage 3 Proposal: https://github.com/tc39/proposal-class-fields
Babel plugin: https://babeljs.io/docs/en/babel-plugin-proposal-class-properties

This does not yet support private class properties yet as that would require
upgrading to babel-eslint@^11 which would require a bunch of other
changes. See: babel/babel-eslint#523
  • Loading branch information
Graham42 committed Jan 29, 2019
1 parent 37e8ea7 commit 5462cfc
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 25 deletions.
58 changes: 35 additions & 23 deletions rules/no-dupe-class-members.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,36 @@ module.exports = {
}
}

/**
* Reports the node if its name has been declared already.
*
* @param {ASTNode} node - A node to get the name.
*/
function checkIfDuplicate(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, messageId: "unexpected", data: { name } });
}
}

return {
// Initializes the stack of state of member declarations.
Program() {
Expand All @@ -93,30 +123,12 @@ module.exports = {
stack.pop();
},

// Reports the node if its name has been declared already.
ClassProperty(node) {
checkIfDuplicate(node);
},

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, messageId: "unexpected", data: { name } });
}
checkIfDuplicate(node);
}
};
}
Expand Down
77 changes: 75 additions & 2 deletions tests/rules/no-dupe-class-members.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const RuleTester = require("../RuleTester");
// Tests
//------------------------------------------------------------------------------

const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
const ruleTester = new RuleTester();

ruleTester.run("no-dupe-class-members", rule, {
valid: [
Expand All @@ -34,7 +34,13 @@ ruleTester.run("no-dupe-class-members", rule, {
"class A { 'foo'() {} 'bar'() {} baz() {} }",
"class A { *'foo'() {} *'bar'() {} *baz() {} }",
"class A { get 'foo'() {} get 'bar'() {} get baz() {} }",
"class A { 1() {} 2() {} }"
"class A { 1() {} 2() {} }",
"class A { foo = 1; bar = 1; }",
"class A { static foo = 1; foo = 1; }",
"class A { foo = 1; } class B { foo = 1; }",
"class A { [foo] = 1; foo = 1; }",
"class A { foo; bar = 1; }",
"class A { foo = () => {}; bar = () => {}; }"
],
invalid: [
{
Expand Down Expand Up @@ -139,6 +145,73 @@ ruleTester.run("no-dupe-class-members", rule, {
data: { name: "foo" }
}
]
},
{
code: "class A { foo = 1; foo = 1; }",
errors: [
{
type: "ClassProperty",
line: 1,
column: 20,
messageId: "unexpected",
data: { name: "foo" }
}
]
},
{
code: "class A { foo = 1; foo = 1; foo = 1; }",
errors: [
{
type: "ClassProperty",
line: 1,
column: 20,
messageId: "unexpected",
data: { name: "foo" }
},
{
type: "ClassProperty",
line: 1,
column: 29,
messageId: "unexpected",
data: { name: "foo" }
}
]
},
{
code: "class A { static foo = 1; static foo = 1; }",
errors: [
{
type: "ClassProperty",
line: 1,
column: 27,
messageId: "unexpected",
data: { name: "foo" }
}
]
},
{
code: "class A { 'foo' = 1; 'foo' = 1; }",
errors: [
{
type: "ClassProperty",
line: 1,
column: 22,
messageId: "unexpected",
data: { name: "foo" }
}
]
},
{
code: "class A { foo = () => {}; foo = () => {}; }",
errors: [
{
type: "ClassProperty",
line: 1,
column: 27,
messageId: "unexpected",
data: { name: "foo" }
}
]
}
]
});

0 comments on commit 5462cfc

Please sign in to comment.