diff --git a/packages/eslint-plugin/docs/rules/naming-convention.md b/packages/eslint-plugin/docs/rules/naming-convention.md index e5bbfb018df..fc4d914e449 100644 --- a/packages/eslint-plugin/docs/rules/naming-convention.md +++ b/packages/eslint-plugin/docs/rules/naming-convention.md @@ -192,31 +192,31 @@ Individual Selectors match specific, well-defined sets. There is no overlap betw - Allowed `modifiers`: `global`, `exported`, `unused`. - Allowed `types`: none. - `parameter` - matches any function parameter. Does not match parameter properties. - - Allowed `modifiers`: `unused`. + - Allowed `modifiers`: `destructured`, `unused`. - Allowed `types`: `boolean`, `string`, `number`, `function`, `array`. - `classProperty` - matches any class property. Does not match properties that have direct function expression or arrow function expression values. - - Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`. + - Allowed `modifiers`: `abstract`, `private`, `protected`, `public`, `readonly`, `requiresQuotes`, `static`. - Allowed `types`: `boolean`, `string`, `number`, `function`, `array`. - `objectLiteralProperty` - matches any object literal property. Does not match properties that have direct function expression or arrow function expression values. - - Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`. + - Allowed `modifiers`: `public`, `requiresQuotes`. - Allowed `types`: `boolean`, `string`, `number`, `function`, `array`. - `typeProperty` - matches any object type property. Does not match properties that have direct function expression or arrow function expression values. - - Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`. + - Allowed `modifiers`: `public`, `readonly`, `requiresQuotes`. - Allowed `types`: `boolean`, `string`, `number`, `function`, `array`. - `parameterProperty` - matches any parameter property. - Allowed `modifiers`: `private`, `protected`, `public`, `readonly`. - Allowed `types`: `boolean`, `string`, `number`, `function`, `array`. - `classMethod` - matches any class method. Also matches properties that have direct function expression or arrow function expression values. Does not match accessors. - - Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`. + - Allowed `modifiers`: `abstract`, `private`, `protected`, `public`, `requiresQuotes`, `static`. - Allowed `types`: none. - `objectLiteralMethod` - matches any object literal method. Also matches properties that have direct function expression or arrow function expression values. Does not match accessors. - - Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`. + - Allowed `modifiers`: `public`, `requiresQuotes`. - Allowed `types`: none. - `typeMethod` - matches any object type method. Also matches properties that have direct function expression or arrow function expression values. Does not match accessors. - - Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`. + - Allowed `modifiers`: `public`, `requiresQuotes`. - Allowed `types`: none. - `accessor` - matches any accessor. - - Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`. + - Allowed `modifiers`: `abstract`, `private`, `protected`, `public`, `requiresQuotes`, `static`. - Allowed `types`: `boolean`, `string`, `number`, `function`, `array`. - `enumMember` - matches any enum member. - Allowed `modifiers`: `requiresQuotes`. diff --git a/packages/eslint-plugin/src/rules/naming-convention-utils/schema.ts b/packages/eslint-plugin/src/rules/naming-convention-utils/schema.ts index 990017db7c9..4d16617f122 100644 --- a/packages/eslint-plugin/src/rules/naming-convention-utils/schema.ts +++ b/packages/eslint-plugin/src/rules/naming-convention-utils/schema.ts @@ -171,47 +171,38 @@ const SCHEMA: JSONSchema.JSONSchema4 = { ...selectorSchema('variable', true, [ 'const', 'destructured', - 'global', 'exported', + 'global', 'unused', ]), - ...selectorSchema('function', false, ['global', 'exported', 'unused']), - ...selectorSchema('parameter', true, ['unused']), + ...selectorSchema('function', false, ['exported', 'global', 'unused']), + ...selectorSchema('parameter', true, ['destructured', 'unused']), ...selectorSchema('memberLike', false, [ + 'abstract', 'private', 'protected', 'public', - 'static', 'readonly', - 'abstract', 'requiresQuotes', + 'static', ]), ...selectorSchema('classProperty', true, [ + 'abstract', 'private', 'protected', 'public', - 'static', 'readonly', - 'abstract', 'requiresQuotes', + 'static', ]), ...selectorSchema('objectLiteralProperty', true, [ - 'private', - 'protected', 'public', - 'static', - 'readonly', - 'abstract', 'requiresQuotes', ]), ...selectorSchema('typeProperty', true, [ - 'private', - 'protected', 'public', - 'static', 'readonly', - 'abstract', 'requiresQuotes', ]), ...selectorSchema('parameterProperty', true, [ @@ -221,54 +212,43 @@ const SCHEMA: JSONSchema.JSONSchema4 = { 'readonly', ]), ...selectorSchema('property', true, [ + 'abstract', 'private', 'protected', 'public', - 'static', 'readonly', - 'abstract', 'requiresQuotes', + 'static', ]), ...selectorSchema('classMethod', false, [ - 'private', - 'protected', - 'public', - 'static', 'abstract', - 'requiresQuotes', - ]), - ...selectorSchema('objectLiteralMethod', false, [ 'private', 'protected', 'public', - 'static', - 'abstract', 'requiresQuotes', + 'static', ]), - ...selectorSchema('typeMethod', false, [ - 'private', - 'protected', + ...selectorSchema('objectLiteralMethod', false, [ 'public', - 'static', - 'abstract', 'requiresQuotes', ]), + ...selectorSchema('typeMethod', false, ['public', 'requiresQuotes']), ...selectorSchema('method', false, [ + 'abstract', 'private', 'protected', 'public', - 'static', - 'abstract', 'requiresQuotes', + 'static', ]), ...selectorSchema('accessor', true, [ + 'abstract', 'private', 'protected', 'public', - 'static', - 'abstract', 'requiresQuotes', + 'static', ]), ...selectorSchema('enumMember', false, ['requiresQuotes']), diff --git a/packages/eslint-plugin/src/rules/naming-convention.ts b/packages/eslint-plugin/src/rules/naming-convention.ts index 338ebfd866b..16e31b62ef8 100644 --- a/packages/eslint-plugin/src/rules/naming-convention.ts +++ b/packages/eslint-plugin/src/rules/naming-convention.ts @@ -174,6 +174,19 @@ export default util.createRule({ return unusedVariables.has(variable); } + function isDestructured(id: TSESTree.Identifier): boolean { + return ( + // `const { x }` + // does not match `const { x: y }` + (id.parent?.type === AST_NODE_TYPES.Property && id.parent.shorthand) || + // `const { x = 2 }` + // does not match const `{ x: y = 2 }` + (id.parent?.type === AST_NODE_TYPES.AssignmentPattern && + id.parent.parent?.type === AST_NODE_TYPES.Property && + id.parent.parent.shorthand) + ); + } + return { // #region variable @@ -199,17 +212,7 @@ export default util.createRule({ identifiers.forEach(id => { const modifiers = new Set(baseModifiers); - if ( - // `const { x }` - // does not match `const { x: y }` - (id.parent?.type === AST_NODE_TYPES.Property && - id.parent.shorthand) || - // `const { x = 2 }` - // does not match const `{ x: y = 2 }` - (id.parent?.type === AST_NODE_TYPES.AssignmentPattern && - id.parent.parent?.type === AST_NODE_TYPES.Property && - id.parent.parent.shorthand) - ) { + if (isDestructured(id)) { modifiers.add(Modifiers.destructured); } @@ -285,6 +288,10 @@ export default util.createRule({ identifiers.forEach(i => { const modifiers = new Set(); + if (isDestructured(i)) { + modifiers.add(Modifiers.destructured); + } + if (isUnused(i.name)) { modifiers.add(Modifiers.unused); } diff --git a/packages/eslint-plugin/tests/rules/naming-convention.test.ts b/packages/eslint-plugin/tests/rules/naming-convention.test.ts index f78b061a969..2a1f1c177cd 100644 --- a/packages/eslint-plugin/tests/rules/naming-convention.test.ts +++ b/packages/eslint-plugin/tests/rules/naming-convention.test.ts @@ -1192,6 +1192,28 @@ ruleTester.run('naming-convention', rule, { }, ], }, + { + code: ` + export function Foo( + { aName }, + { anotherName = 1 }, + { ignored: IgnoredDueToModifiers1 }, + { ignored: IgnoredDueToModifiers1 = 2 }, + IgnoredDueToModifiers2, + ) {} + `, + options: [ + { + selector: 'default', + format: ['PascalCase'], + }, + { + selector: 'parameter', + modifiers: ['destructured'], + format: ['camelCase'], + }, + ], + }, { code: ` class Ignored { @@ -1965,9 +1987,10 @@ ruleTester.run('naming-convention', rule, { { code: ` const { some_name1 } = {}; - const { ignore: IgnoredDueToModifiers1 } = {}; const { some_name2 = 2 } = {}; - const IgnoredDueToModifiers2 = 1; + const { ignored: IgnoredDueToModifiers1 } = {}; + const { ignored: IgnoredDueToModifiers2 = 3 } = {}; + const IgnoredDueToModifiers3 = 1; `, options: [ { @@ -1982,6 +2005,29 @@ ruleTester.run('naming-convention', rule, { ], errors: Array(2).fill({ messageId: 'doesNotMatchFormat' }), }, + { + code: ` + export function Foo( + { aName }, + { anotherName = 1 }, + { ignored: IgnoredDueToModifiers1 }, + { ignored: IgnoredDueToModifiers1 = 2 }, + IgnoredDueToModifiers2, + ) {} + `, + options: [ + { + selector: 'default', + format: ['PascalCase'], + }, + { + selector: 'parameter', + modifiers: ['destructured'], + format: ['UPPER_CASE'], + }, + ], + errors: Array(2).fill({ messageId: 'doesNotMatchFormat' }), + }, { code: ` class Ignored {