Skip to content

Commit

Permalink
feat(eslint-plugin): [naming-convention] add support for "override" a…
Browse files Browse the repository at this point in the history
…nd "async" modifiers (#5310)
  • Loading branch information
eliasm307 committed Sep 7, 2022
1 parent 45e2912 commit 58dbdaf
Show file tree
Hide file tree
Showing 5 changed files with 527 additions and 14 deletions.
23 changes: 12 additions & 11 deletions packages/eslint-plugin/docs/rules/naming-convention.md
Expand Up @@ -173,7 +173,8 @@ If these are provided, the identifier must start with one of the provided values
- `unused` - matches anything that is not used.
- `requiresQuotes` - matches any name that requires quotes as it is not a valid identifier (i.e. has a space, a dash, etc in it).
- `public` - matches any member that is either explicitly declared as `public`, or has no visibility modifier (i.e. implicitly public).
- `readonly`, `static`, `abstract`, `protected`, `private` - matches any member explicitly declared with the given modifier.
- `readonly`, `static`, `abstract`, `protected`, `private`, `override` - matches any member explicitly declared with the given modifier.
- `async` - matches any method, function, or function variable which is async via the `async` keyword (e.g. does not match functions that return promises without using `async` keyword)
- `types` allows you to specify which types to match. This option supports simple, primitive types only (`boolean`, `string`, `number`, `array`, `function`).
- The name must match _one_ of the types.
- **_NOTE - Using this option will require that you lint with type information._**
Expand All @@ -196,16 +197,16 @@ There are two types of selectors, individual selectors, and grouped selectors.
Individual Selectors match specific, well-defined sets. There is no overlap between each of the individual selectors.

- `variable` - matches any `var` / `let` / `const` variable name.
- Allowed `modifiers`: `const`, `destructured`, `global`, `exported`, `unused`.
- Allowed `modifiers`: `const`, `destructured`, `global`, `exported`, `unused`, `override`, `async`.
- Allowed `types`: `boolean`, `string`, `number`, `function`, `array`.
- `function` - matches any named function declaration or named function expression.
- Allowed `modifiers`: `global`, `exported`, `unused`.
- Allowed `modifiers`: `global`, `exported`, `unused`, `async`.
- Allowed `types`: none.
- `parameter` - matches any function parameter. Does not match parameter properties.
- 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`: `abstract`, `private`, `protected`, `public`, `readonly`, `requiresQuotes`, `static`.
- Allowed `modifiers`: `abstract`, `private`, `protected`, `public`, `readonly`, `requiresQuotes`, `static`, `override`.
- 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`: `public`, `requiresQuotes`.
Expand All @@ -217,16 +218,16 @@ Individual Selectors match specific, well-defined sets. There is no overlap betw
- 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`: `abstract`, `private`, `protected`, `public`, `requiresQuotes`, `static`.
- Allowed `modifiers`: `abstract`, `private`, `protected`, `public`, `requiresQuotes`, `static`, `override`, `async`.
- 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`: `public`, `requiresQuotes`.
- Allowed `modifiers`: `public`, `requiresQuotes`, `async`.
- 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`: `public`, `requiresQuotes`.
- Allowed `types`: none.
- `accessor` - matches any accessor.
- Allowed `modifiers`: `abstract`, `private`, `protected`, `public`, `requiresQuotes`, `static`.
- Allowed `modifiers`: `abstract`, `private`, `protected`, `public`, `requiresQuotes`, `static`, `override`.
- Allowed `types`: `boolean`, `string`, `number`, `function`, `array`.
- `enumMember` - matches any enum member.
- Allowed `modifiers`: `requiresQuotes`.
Expand Down Expand Up @@ -255,19 +256,19 @@ Group Selectors are provided for convenience, and essentially bundle up sets of
- Allowed `modifiers`: all modifiers.
- Allowed `types`: none.
- `variableLike` - matches the same as `variable`, `function` and `parameter`.
- Allowed `modifiers`: `unused`.
- Allowed `modifiers`: `unused`, `async`.
- Allowed `types`: none.
- `memberLike` - matches the same as `property`, `parameterProperty`, `method`, `accessor`, `enumMember`.
- Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`.
- Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`, `override`, `async`.
- Allowed `types`: none.
- `typeLike` - matches the same as `class`, `interface`, `typeAlias`, `enum`, `typeParameter`.
- Allowed `modifiers`: `abstract`, `unused`.
- Allowed `types`: none.
- `property` - matches the same as `classProperty`, `objectLiteralProperty`, `typeProperty`.
- Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`.
- Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`, `override`, `async`.
- Allowed `types`: `boolean`, `string`, `number`, `function`, `array`.
- `method` - matches the same as `classMethod`, `objectLiteralMethod`, `typeMethod`.
- Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`.
- Allowed `modifiers`: `private`, `protected`, `public`, `static`, `readonly`, `abstract`, `requiresQuotes`, `override`, `async`.
- Allowed `types`: none.

## FAQ
Expand Down
Expand Up @@ -102,6 +102,10 @@ enum Modifiers {
unused = 1 << 10,
// properties that require quoting
requiresQuotes = 1 << 11,
// class members that are overridden
override = 1 << 12,
// class methods, object function properties, or functions that are async via the `async` keyword
async = 1 << 13,

// make sure TypeModifiers starts at Modifiers + 1 or else sorting won't work
}
Expand Down
21 changes: 19 additions & 2 deletions packages/eslint-plugin/src/rules/naming-convention-utils/schema.ts
Expand Up @@ -167,15 +167,21 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
selectorsSchema(),
...selectorSchema('default', false, util.getEnumNames(Modifiers)),

...selectorSchema('variableLike', false, ['unused']),
...selectorSchema('variableLike', false, ['unused', 'async']),
...selectorSchema('variable', true, [
'const',
'destructured',
'exported',
'global',
'unused',
'async',
]),
...selectorSchema('function', false, [
'exported',
'global',
'unused',
'async',
]),
...selectorSchema('function', false, ['exported', 'global', 'unused']),
...selectorSchema('parameter', true, ['destructured', 'unused']),

...selectorSchema('memberLike', false, [
Expand All @@ -186,6 +192,8 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
'readonly',
'requiresQuotes',
'static',
'override',
'async',
]),
...selectorSchema('classProperty', true, [
'abstract',
Expand All @@ -195,6 +203,7 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
'readonly',
'requiresQuotes',
'static',
'override',
]),
...selectorSchema('objectLiteralProperty', true, [
'public',
Expand All @@ -219,6 +228,8 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
'readonly',
'requiresQuotes',
'static',
'override',
'async',
]),

...selectorSchema('classMethod', false, [
Expand All @@ -228,10 +239,13 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
'public',
'requiresQuotes',
'static',
'override',
'async',
]),
...selectorSchema('objectLiteralMethod', false, [
'public',
'requiresQuotes',
'async',
]),
...selectorSchema('typeMethod', false, ['public', 'requiresQuotes']),
...selectorSchema('method', false, [
Expand All @@ -241,6 +255,8 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
'public',
'requiresQuotes',
'static',
'override',
'async',
]),
...selectorSchema('accessor', true, [
'abstract',
Expand All @@ -249,6 +265,7 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
'public',
'requiresQuotes',
'static',
'override',
]),
...selectorSchema('enumMember', false, ['requiresQuotes']),

Expand Down
60 changes: 60 additions & 0 deletions packages/eslint-plugin/src/rules/naming-convention.ts
Expand Up @@ -138,6 +138,9 @@ export default util.createRule<Options, MessageIds>({
if ('readonly' in node && node.readonly) {
modifiers.add(Modifiers.readonly);
}
if ('override' in node && node.override) {
modifiers.add(Modifiers.override);
}
if (
node.type === AST_NODE_TYPES.TSAbstractPropertyDefinition ||
node.type === AST_NODE_TYPES.TSAbstractMethodDefinition
Expand Down Expand Up @@ -182,6 +185,34 @@ export default util.createRule<Options, MessageIds>({
);
}

function isAsyncMemberOrProperty(
propertyOrMemberNode:
| TSESTree.PropertyNonComputedName
| TSESTree.TSMethodSignatureNonComputedName
| TSESTree.PropertyDefinitionNonComputedName
| TSESTree.TSAbstractPropertyDefinitionNonComputedName
| TSESTree.MethodDefinitionNonComputedName
| TSESTree.TSAbstractMethodDefinitionNonComputedName,
): boolean {
return Boolean(
'value' in propertyOrMemberNode &&
propertyOrMemberNode.value &&
'async' in propertyOrMemberNode.value &&
propertyOrMemberNode.value.async,
);
}

function isAsyncVariableIdentifier(id: TSESTree.Identifier): boolean {
return Boolean(
id.parent &&
(('async' in id.parent && id.parent.async) ||
('init' in id.parent &&
id.parent.init &&
'async' in id.parent.init &&
id.parent.init.async)),
);
}

return {
// #region variable

Expand Down Expand Up @@ -219,6 +250,10 @@ export default util.createRule<Options, MessageIds>({
modifiers.add(Modifiers.unused);
}

if (isAsyncVariableIdentifier(id)) {
modifiers.add(Modifiers.async);
}

validator(id, modifiers);
});
},
Expand Down Expand Up @@ -254,6 +289,10 @@ export default util.createRule<Options, MessageIds>({
modifiers.add(Modifiers.unused);
}

if (node.async) {
modifiers.add(Modifiers.async);
}

validator(node.id, modifiers);
},

Expand Down Expand Up @@ -291,6 +330,10 @@ export default util.createRule<Options, MessageIds>({
modifiers.add(Modifiers.unused);
}

if (node.async) {
modifiers.add(Modifiers.async);
}

validator(i, modifiers);
});
});
Expand Down Expand Up @@ -360,6 +403,11 @@ export default util.createRule<Options, MessageIds>({
| TSESTree.TSMethodSignatureNonComputedName,
): void {
const modifiers = new Set<Modifiers>([Modifiers.public]);

if (isAsyncMemberOrProperty(node)) {
modifiers.add(Modifiers.async);
}

handleMember(validators.objectLiteralMethod, node, modifiers);
},

Expand All @@ -376,6 +424,11 @@ export default util.createRule<Options, MessageIds>({
| TSESTree.TSAbstractMethodDefinitionNonComputedName,
): void {
const modifiers = getMemberModifiers(node);

if (isAsyncMemberOrProperty(node)) {
modifiers.add(Modifiers.async);
}

handleMember(validators.classMethod, node, modifiers);
},

Expand Down Expand Up @@ -404,6 +457,13 @@ export default util.createRule<Options, MessageIds>({
handleMember(validators.accessor, node, modifiers);
},

'TSAbstractMethodDefinition[computed = false]:matches([kind = "get"], [kind = "set"])'(
node: TSESTree.MethodDefinitionNonComputedName,
): void {
const modifiers = getMemberModifiers(node);
handleMember(validators.accessor, node, modifiers);
},

// #endregion accessor

// #region enumMember
Expand Down

0 comments on commit 58dbdaf

Please sign in to comment.