Skip to content

Commit 525d2ff

Browse files
authored
feat(eslint-plugin): [naming-convention] allow destructured modifier for parameter selector (typescript-eslint#2829)
Fixes typescript-eslint#2828
1 parent 050023a commit 525d2ff

File tree

4 files changed

+90
-57
lines changed

4 files changed

+90
-57
lines changed

packages/eslint-plugin/docs/rules/naming-convention.md

+8-8
Original file line numberDiff line numberDiff line change
@@ -192,31 +192,31 @@ Individual Selectors match specific, well-defined sets. There is no overlap betw
192192
- Allowed `modifiers`: `global`, `exported`, `unused`.
193193
- Allowed `types`: none.
194194
- `parameter` - matches any function parameter. Does not match parameter properties.
195-
- Allowed `modifiers`: `unused`.
195+
- Allowed `modifiers`: `destructured`, `unused`.
196196
- Allowed `types`: `boolean`, `string`, `number`, `function`, `array`.
197197
- `classProperty` - matches any class property. Does not match properties that have direct function expression or arrow function expression values.
198-
- Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`.
198+
- Allowed `modifiers`: `abstract`, `private`, `protected`, `public`, `readonly`, `requiresQuotes`, `static`.
199199
- Allowed `types`: `boolean`, `string`, `number`, `function`, `array`.
200200
- `objectLiteralProperty` - matches any object literal property. Does not match properties that have direct function expression or arrow function expression values.
201-
- Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`.
201+
- Allowed `modifiers`: `public`, `requiresQuotes`.
202202
- Allowed `types`: `boolean`, `string`, `number`, `function`, `array`.
203203
- `typeProperty` - matches any object type property. Does not match properties that have direct function expression or arrow function expression values.
204-
- Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`.
204+
- Allowed `modifiers`: `public`, `readonly`, `requiresQuotes`.
205205
- Allowed `types`: `boolean`, `string`, `number`, `function`, `array`.
206206
- `parameterProperty` - matches any parameter property.
207207
- Allowed `modifiers`: `private`, `protected`, `public`, `readonly`.
208208
- Allowed `types`: `boolean`, `string`, `number`, `function`, `array`.
209209
- `classMethod` - matches any class method. Also matches properties that have direct function expression or arrow function expression values. Does not match accessors.
210-
- Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`.
210+
- Allowed `modifiers`: `abstract`, `private`, `protected`, `public`, `requiresQuotes`, `static`.
211211
- Allowed `types`: none.
212212
- `objectLiteralMethod` - matches any object literal method. Also matches properties that have direct function expression or arrow function expression values. Does not match accessors.
213-
- Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`.
213+
- Allowed `modifiers`: `public`, `requiresQuotes`.
214214
- Allowed `types`: none.
215215
- `typeMethod` - matches any object type method. Also matches properties that have direct function expression or arrow function expression values. Does not match accessors.
216-
- Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`.
216+
- Allowed `modifiers`: `public`, `requiresQuotes`.
217217
- Allowed `types`: none.
218218
- `accessor` - matches any accessor.
219-
- Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`.
219+
- Allowed `modifiers`: `abstract`, `private`, `protected`, `public`, `requiresQuotes`, `static`.
220220
- Allowed `types`: `boolean`, `string`, `number`, `function`, `array`.
221221
- `enumMember` - matches any enum member.
222222
- Allowed `modifiers`: `requiresQuotes`.

packages/eslint-plugin/src/rules/naming-convention-utils/schema.ts

+16-36
Original file line numberDiff line numberDiff line change
@@ -171,47 +171,38 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
171171
...selectorSchema('variable', true, [
172172
'const',
173173
'destructured',
174-
'global',
175174
'exported',
175+
'global',
176176
'unused',
177177
]),
178-
...selectorSchema('function', false, ['global', 'exported', 'unused']),
179-
...selectorSchema('parameter', true, ['unused']),
178+
...selectorSchema('function', false, ['exported', 'global', 'unused']),
179+
...selectorSchema('parameter', true, ['destructured', 'unused']),
180180

181181
...selectorSchema('memberLike', false, [
182+
'abstract',
182183
'private',
183184
'protected',
184185
'public',
185-
'static',
186186
'readonly',
187-
'abstract',
188187
'requiresQuotes',
188+
'static',
189189
]),
190190
...selectorSchema('classProperty', true, [
191+
'abstract',
191192
'private',
192193
'protected',
193194
'public',
194-
'static',
195195
'readonly',
196-
'abstract',
197196
'requiresQuotes',
197+
'static',
198198
]),
199199
...selectorSchema('objectLiteralProperty', true, [
200-
'private',
201-
'protected',
202200
'public',
203-
'static',
204-
'readonly',
205-
'abstract',
206201
'requiresQuotes',
207202
]),
208203
...selectorSchema('typeProperty', true, [
209-
'private',
210-
'protected',
211204
'public',
212-
'static',
213205
'readonly',
214-
'abstract',
215206
'requiresQuotes',
216207
]),
217208
...selectorSchema('parameterProperty', true, [
@@ -221,54 +212,43 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
221212
'readonly',
222213
]),
223214
...selectorSchema('property', true, [
215+
'abstract',
224216
'private',
225217
'protected',
226218
'public',
227-
'static',
228219
'readonly',
229-
'abstract',
230220
'requiresQuotes',
221+
'static',
231222
]),
232223

233224
...selectorSchema('classMethod', false, [
234-
'private',
235-
'protected',
236-
'public',
237-
'static',
238225
'abstract',
239-
'requiresQuotes',
240-
]),
241-
...selectorSchema('objectLiteralMethod', false, [
242226
'private',
243227
'protected',
244228
'public',
245-
'static',
246-
'abstract',
247229
'requiresQuotes',
230+
'static',
248231
]),
249-
...selectorSchema('typeMethod', false, [
250-
'private',
251-
'protected',
232+
...selectorSchema('objectLiteralMethod', false, [
252233
'public',
253-
'static',
254-
'abstract',
255234
'requiresQuotes',
256235
]),
236+
...selectorSchema('typeMethod', false, ['public', 'requiresQuotes']),
257237
...selectorSchema('method', false, [
238+
'abstract',
258239
'private',
259240
'protected',
260241
'public',
261-
'static',
262-
'abstract',
263242
'requiresQuotes',
243+
'static',
264244
]),
265245
...selectorSchema('accessor', true, [
246+
'abstract',
266247
'private',
267248
'protected',
268249
'public',
269-
'static',
270-
'abstract',
271250
'requiresQuotes',
251+
'static',
272252
]),
273253
...selectorSchema('enumMember', false, ['requiresQuotes']),
274254

packages/eslint-plugin/src/rules/naming-convention.ts

+18-11
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,19 @@ export default util.createRule<Options, MessageIds>({
174174
return unusedVariables.has(variable);
175175
}
176176

177+
function isDestructured(id: TSESTree.Identifier): boolean {
178+
return (
179+
// `const { x }`
180+
// does not match `const { x: y }`
181+
(id.parent?.type === AST_NODE_TYPES.Property && id.parent.shorthand) ||
182+
// `const { x = 2 }`
183+
// does not match const `{ x: y = 2 }`
184+
(id.parent?.type === AST_NODE_TYPES.AssignmentPattern &&
185+
id.parent.parent?.type === AST_NODE_TYPES.Property &&
186+
id.parent.parent.shorthand)
187+
);
188+
}
189+
177190
return {
178191
// #region variable
179192

@@ -199,17 +212,7 @@ export default util.createRule<Options, MessageIds>({
199212
identifiers.forEach(id => {
200213
const modifiers = new Set(baseModifiers);
201214

202-
if (
203-
// `const { x }`
204-
// does not match `const { x: y }`
205-
(id.parent?.type === AST_NODE_TYPES.Property &&
206-
id.parent.shorthand) ||
207-
// `const { x = 2 }`
208-
// does not match const `{ x: y = 2 }`
209-
(id.parent?.type === AST_NODE_TYPES.AssignmentPattern &&
210-
id.parent.parent?.type === AST_NODE_TYPES.Property &&
211-
id.parent.parent.shorthand)
212-
) {
215+
if (isDestructured(id)) {
213216
modifiers.add(Modifiers.destructured);
214217
}
215218

@@ -285,6 +288,10 @@ export default util.createRule<Options, MessageIds>({
285288
identifiers.forEach(i => {
286289
const modifiers = new Set<Modifiers>();
287290

291+
if (isDestructured(i)) {
292+
modifiers.add(Modifiers.destructured);
293+
}
294+
288295
if (isUnused(i.name)) {
289296
modifiers.add(Modifiers.unused);
290297
}

packages/eslint-plugin/tests/rules/naming-convention.test.ts

+48-2
Original file line numberDiff line numberDiff line change
@@ -1192,6 +1192,28 @@ ruleTester.run('naming-convention', rule, {
11921192
},
11931193
],
11941194
},
1195+
{
1196+
code: `
1197+
export function Foo(
1198+
{ aName },
1199+
{ anotherName = 1 },
1200+
{ ignored: IgnoredDueToModifiers1 },
1201+
{ ignored: IgnoredDueToModifiers1 = 2 },
1202+
IgnoredDueToModifiers2,
1203+
) {}
1204+
`,
1205+
options: [
1206+
{
1207+
selector: 'default',
1208+
format: ['PascalCase'],
1209+
},
1210+
{
1211+
selector: 'parameter',
1212+
modifiers: ['destructured'],
1213+
format: ['camelCase'],
1214+
},
1215+
],
1216+
},
11951217
{
11961218
code: `
11971219
class Ignored {
@@ -1965,9 +1987,10 @@ ruleTester.run('naming-convention', rule, {
19651987
{
19661988
code: `
19671989
const { some_name1 } = {};
1968-
const { ignore: IgnoredDueToModifiers1 } = {};
19691990
const { some_name2 = 2 } = {};
1970-
const IgnoredDueToModifiers2 = 1;
1991+
const { ignored: IgnoredDueToModifiers1 } = {};
1992+
const { ignored: IgnoredDueToModifiers2 = 3 } = {};
1993+
const IgnoredDueToModifiers3 = 1;
19711994
`,
19721995
options: [
19731996
{
@@ -1982,6 +2005,29 @@ ruleTester.run('naming-convention', rule, {
19822005
],
19832006
errors: Array(2).fill({ messageId: 'doesNotMatchFormat' }),
19842007
},
2008+
{
2009+
code: `
2010+
export function Foo(
2011+
{ aName },
2012+
{ anotherName = 1 },
2013+
{ ignored: IgnoredDueToModifiers1 },
2014+
{ ignored: IgnoredDueToModifiers1 = 2 },
2015+
IgnoredDueToModifiers2,
2016+
) {}
2017+
`,
2018+
options: [
2019+
{
2020+
selector: 'default',
2021+
format: ['PascalCase'],
2022+
},
2023+
{
2024+
selector: 'parameter',
2025+
modifiers: ['destructured'],
2026+
format: ['UPPER_CASE'],
2027+
},
2028+
],
2029+
errors: Array(2).fill({ messageId: 'doesNotMatchFormat' }),
2030+
},
19852031
{
19862032
code: `
19872033
class Ignored {

0 commit comments

Comments
 (0)