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 (typescript-eslint#5310)
  • Loading branch information
eliasm307 committed Sep 6, 2022
1 parent f7c5deb commit 95d1c76
Show file tree
Hide file tree
Showing 6 changed files with 500 additions and 71 deletions.
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
22 changes: 19 additions & 3 deletions packages/eslint-plugin/src/rules/naming-convention-utils/schema.ts
@@ -1,4 +1,6 @@
import { JSONSchema } from '@typescript-eslint/utils';

import * as util from '../../util';
import {
IndividualAndMetaSelectorsString,
MetaSelectors,
Expand All @@ -9,7 +11,6 @@ import {
TypeModifiers,
UnderscoreOptions,
} from './enums';
import * as util from '../../util';

const UNDERSCORE_SCHEMA: JSONSchema.JSONSchema4 = {
type: 'string',
Expand Down Expand Up @@ -167,15 +168,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 +193,7 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
'readonly',
'requiresQuotes',
'static',
'override',
]),
...selectorSchema('classProperty', true, [
'abstract',
Expand All @@ -195,6 +203,7 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
'readonly',
'requiresQuotes',
'static',
'override',
]),
...selectorSchema('objectLiteralProperty', true, [
'public',
Expand All @@ -210,6 +219,7 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
'protected',
'public',
'readonly',
'override',
]),
...selectorSchema('property', true, [
'abstract',
Expand All @@ -219,6 +229,7 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
'readonly',
'requiresQuotes',
'static',
'override',
]),

...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 Down
@@ -1,4 +1,6 @@
import { TSESLint, TSESTree } from '@typescript-eslint/utils';

import { NamingConventionRuleMessageIds, Options } from '../naming-convention';
import {
IndividualAndMetaSelectorsString,
MetaSelectors,
Expand All @@ -13,7 +15,6 @@ import {
UnderscoreOptions,
UnderscoreOptionsString,
} from './enums';
import { MessageIds, Options } from '../naming-convention';

interface MatchRegex {
regex: string;
Expand Down Expand Up @@ -64,7 +65,9 @@ type ValidatorFunction = (
modifiers?: Set<Modifiers>,
) => void;
type ParsedOptions = Record<SelectorsString, null | ValidatorFunction>;
type Context = Readonly<TSESLint.RuleContext<MessageIds, Options>>;
type Context = Readonly<
TSESLint.RuleContext<NamingConventionRuleMessageIds, Options>
>;

export type {
Context,
Expand Down
123 changes: 64 additions & 59 deletions packages/eslint-plugin/src/rules/naming-convention.ts
@@ -1,6 +1,6 @@
import { AST_NODE_TYPES, TSESLint, TSESTree } from '@typescript-eslint/utils';
import { PatternVisitor } from '@typescript-eslint/scope-manager';
import type { ScriptTarget } from 'typescript';
import { AST_NODE_TYPES, TSESLint, TSESTree } from '@typescript-eslint/utils';

import * as util from '../util';
import {
Context,
Expand All @@ -11,6 +11,8 @@ import {
ValidatorFunction,
} from './naming-convention-utils';

import type { ScriptTarget } from 'typescript';

type MessageIds =
| 'unexpectedUnderscore'
| 'missingUnderscore'
Expand Down Expand Up @@ -138,11 +140,16 @@ export default util.createRule<Options, MessageIds>({
if ('readonly' in node && node.readonly) {
modifiers.add(Modifiers.readonly);
}
if (
node.type === AST_NODE_TYPES.TSAbstractPropertyDefinition ||
node.type === AST_NODE_TYPES.TSAbstractMethodDefinition
) {
modifiers.add(Modifiers.abstract);
if ('override' in node && node.override) {
modifiers.add(Modifiers.override);
}
{
if (
node.type === AST_NODE_TYPES.TSAbstractPropertyDefinition ||
node.type === AST_NODE_TYPES.TSAbstractMethodDefinition
) {
modifiers.add(Modifiers.abstract);
}
}

return modifiers;
Expand Down Expand Up @@ -182,9 +189,35 @@ export default util.createRule<Options, MessageIds>({
);
}

return {
// #region variable
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 {
VariableDeclarator(node: TSESTree.VariableDeclarator): void {
const validator = validators.variable;
if (!validator) {
Expand Down Expand Up @@ -219,14 +252,14 @@ export default util.createRule<Options, MessageIds>({
modifiers.add(Modifiers.unused);
}

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

validator(id, modifiers);
});
},

// #endregion

// #region function

'FunctionDeclaration, TSDeclareFunction, FunctionExpression'(
node:
| TSESTree.FunctionDeclaration
Expand Down Expand Up @@ -254,12 +287,12 @@ export default util.createRule<Options, MessageIds>({
modifiers.add(Modifiers.unused);
}

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

validator(node.id, modifiers);
},

// #endregion function

// #region parameter
'FunctionDeclaration, TSDeclareFunction, TSEmptyBodyFunctionExpression, FunctionExpression, ArrowFunctionExpression'(
node:
| TSESTree.FunctionDeclaration
Expand Down Expand Up @@ -291,15 +324,15 @@ export default util.createRule<Options, MessageIds>({
modifiers.add(Modifiers.unused);
}

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

validator(i, modifiers);
});
});
},

// #endregion parameter

// #region parameterProperty

TSParameterProperty(node): void {
const validator = validators.parameterProperty;
if (!validator) {
Expand All @@ -315,10 +348,6 @@ export default util.createRule<Options, MessageIds>({
});
},

// #endregion parameterProperty

// #region property

':not(ObjectPattern) > Property[computed = false][kind = "init"][value.type != "ArrowFunctionExpression"][value.type != "FunctionExpression"][value.type != "TSEmptyBodyFunctionExpression"]'(
node: TSESTree.PropertyNonComputedName,
): void {
Expand Down Expand Up @@ -346,10 +375,6 @@ export default util.createRule<Options, MessageIds>({
handleMember(validators.typeProperty, node, modifiers);
},

// #endregion property

// #region method

[[
'Property[computed = false][kind = "init"][value.type = "ArrowFunctionExpression"]',
'Property[computed = false][kind = "init"][value.type = "FunctionExpression"]',
Expand All @@ -360,6 +385,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 +406,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 All @@ -386,10 +421,6 @@ export default util.createRule<Options, MessageIds>({
handleMember(validators.typeMethod, node, modifiers);
},

// #endregion method

// #region accessor

'Property[computed = false]:matches([kind = "get"], [kind = "set"])'(
node: TSESTree.PropertyNonComputedName,
): void {
Expand All @@ -404,10 +435,6 @@ export default util.createRule<Options, MessageIds>({
handleMember(validators.accessor, node, modifiers);
},

// #endregion accessor

// #region enumMember

// computed is optional, so can't do [computed = false]
'TSEnumMember[computed != true]'(
node: TSESTree.TSEnumMemberNonComputedName,
Expand All @@ -427,10 +454,6 @@ export default util.createRule<Options, MessageIds>({
validator(id, modifiers);
},

// #endregion enumMember

// #region class

'ClassDeclaration, ClassExpression'(
node: TSESTree.ClassDeclaration | TSESTree.ClassExpression,
): void {
Expand Down Expand Up @@ -463,10 +486,6 @@ export default util.createRule<Options, MessageIds>({
validator(id, modifiers);
},

// #endregion class

// #region interface

TSInterfaceDeclaration(node): void {
const validator = validators.interface;
if (!validator) {
Expand All @@ -487,10 +506,6 @@ export default util.createRule<Options, MessageIds>({
validator(node.id, modifiers);
},

// #endregion interface

// #region typeAlias

TSTypeAliasDeclaration(node): void {
const validator = validators.typeAlias;
if (!validator) {
Expand All @@ -511,10 +526,6 @@ export default util.createRule<Options, MessageIds>({
validator(node.id, modifiers);
},

// #endregion typeAlias

// #region enum

TSEnumDeclaration(node): void {
const validator = validators.enum;
if (!validator) {
Expand All @@ -536,10 +547,6 @@ export default util.createRule<Options, MessageIds>({
validator(node.id, modifiers);
},

// #endregion enum

// #region typeParameter

'TSTypeParameterDeclaration > TSTypeParameter'(
node: TSESTree.TSTypeParameter,
): void {
Expand All @@ -557,8 +564,6 @@ export default util.createRule<Options, MessageIds>({

validator(node.name, modifiers);
},

// #endregion typeParameter
};
},
});
Expand Down

0 comments on commit 95d1c76

Please sign in to comment.