Skip to content

Commit b006667

Browse files
a-tarasyukJamesHenry
authored andcommitted
fix(eslint-plugin): [member-naming] should match constructor args (#771)
1 parent 9f82099 commit b006667

File tree

2 files changed

+124
-15
lines changed

2 files changed

+124
-15
lines changed

Diff for: packages/eslint-plugin/src/rules/member-naming.ts

+54-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { TSESTree } from '@typescript-eslint/experimental-utils';
1+
import {
2+
TSESTree,
3+
AST_NODE_TYPES,
4+
} from '@typescript-eslint/experimental-utils';
25
import * as util from '../util';
36

47
interface Config<T = string> {
@@ -61,37 +64,73 @@ export default util.createRule<Options, MessageIds>({
6164
return acc;
6265
}, {});
6366

64-
/**
65-
* Check that the property name matches the convention for its
66-
* accessibility.
67-
* @param {ASTNode} node the named node to evaluate.
68-
* @returns {void}
69-
* @private
70-
*/
67+
function getParameterNode(
68+
node: TSESTree.TSParameterProperty,
69+
): TSESTree.Identifier | null {
70+
if (node.parameter.type === AST_NODE_TYPES.AssignmentPattern) {
71+
return node.parameter.left as TSESTree.Identifier;
72+
}
73+
74+
if (node.parameter.type === AST_NODE_TYPES.Identifier) {
75+
return node.parameter;
76+
}
77+
78+
return null;
79+
}
80+
81+
function validateParameterName(node: TSESTree.TSParameterProperty): void {
82+
const parameterNode = getParameterNode(node);
83+
if (!parameterNode) {
84+
return;
85+
}
86+
87+
validate(parameterNode, parameterNode.name, node.accessibility);
88+
}
89+
7190
function validateName(
7291
node: TSESTree.MethodDefinition | TSESTree.ClassProperty,
7392
): void {
74-
const name = util.getNameFromClassMember(node, sourceCode);
75-
const accessibility: Modifiers = node.accessibility || 'public';
76-
const convention = conventions[accessibility];
77-
78-
const method = node as TSESTree.MethodDefinition;
79-
if (method.kind === 'constructor') {
93+
if (
94+
node.type === AST_NODE_TYPES.MethodDefinition &&
95+
node.kind === 'constructor'
96+
) {
8097
return;
8198
}
8299

100+
validate(
101+
node.key,
102+
util.getNameFromClassMember(node, sourceCode),
103+
node.accessibility,
104+
);
105+
}
106+
107+
/**
108+
* Check that the name matches the convention for its accessibility.
109+
* @param {ASTNode} node the named node to evaluate.
110+
* @param {string} name
111+
* @param {Modifiers} accessibility
112+
* @returns {void}
113+
* @private
114+
*/
115+
function validate(
116+
node: TSESTree.Identifier | TSESTree.Expression,
117+
name: string,
118+
accessibility: Modifiers = 'public',
119+
): void {
120+
const convention = conventions[accessibility];
83121
if (!convention || convention.test(name)) {
84122
return;
85123
}
86124

87125
context.report({
88-
node: node.key,
126+
node,
89127
messageId: 'incorrectName',
90128
data: { accessibility, name, convention },
91129
});
92130
}
93131

94132
return {
133+
TSParameterProperty: validateParameterName,
95134
MethodDefinition: validateName,
96135
ClassProperty: validateName,
97136
};

Diff for: packages/eslint-plugin/tests/rules/member-naming.test.ts

+70
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,30 @@ class Class {
8686
},
8787
],
8888
},
89+
90+
{
91+
code: `
92+
class Test {
93+
constructor(public __a: string, protected __b: string, private __c: string = 100) {}
94+
}
95+
`,
96+
options: [
97+
{
98+
protected: '^__',
99+
private: '^__',
100+
public: '^__',
101+
},
102+
],
103+
},
104+
{
105+
code:
106+
// Semantically invalid test case, TS has to throw an error.
107+
`
108+
class Foo {
109+
constructor(private ...name: string[], private [test]: [string]) {}
110+
}
111+
`,
112+
},
89113
],
90114
invalid: [
91115
{
@@ -329,5 +353,51 @@ class Class {
329353
},
330354
],
331355
},
356+
{
357+
code: `
358+
class Test {
359+
constructor(public a: string, protected b: string, private c: string = 100) {}
360+
}
361+
`,
362+
options: [
363+
{
364+
public: '^__',
365+
protected: '^__',
366+
private: '^__',
367+
},
368+
],
369+
errors: [
370+
{
371+
messageId: 'incorrectName',
372+
data: {
373+
accessibility: 'public',
374+
convention: '/^__/',
375+
name: 'a',
376+
},
377+
line: 3,
378+
column: 24,
379+
},
380+
{
381+
messageId: 'incorrectName',
382+
data: {
383+
accessibility: 'protected',
384+
convention: '/^__/',
385+
name: 'b',
386+
},
387+
line: 3,
388+
column: 45,
389+
},
390+
{
391+
messageId: 'incorrectName',
392+
data: {
393+
accessibility: 'private',
394+
convention: '/^__/',
395+
name: 'c',
396+
},
397+
line: 3,
398+
column: 64,
399+
},
400+
],
401+
},
332402
],
333403
});

0 commit comments

Comments
 (0)