Skip to content

Commit

Permalink
feat(eslint-plugin): [naming-convention] support the auto-accessor sy…
Browse files Browse the repository at this point in the history
…ntax (#8084)
  • Loading branch information
arka1002 committed Feb 22, 2024
1 parent 13429cc commit f7198db
Show file tree
Hide file tree
Showing 11 changed files with 312 additions and 26 deletions.
10 changes: 8 additions & 2 deletions packages/eslint-plugin/docs/rules/naming-convention.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,10 @@ 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.

- `accessor` - matches any accessor.
- `classicAccessor` - matches any accessor. It refers to the methods attached to `get` and `set` syntax.
- Allowed `modifiers`: `abstract`, `override`, `private`, `protected`, `public`, `requiresQuotes`, `static`.
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`.
- `autoAccessor` - matches any auto-accessor. An auto-accessor is just a class field starting with an `accessor` keyword.
- Allowed `modifiers`: `abstract`, `override`, `private`, `protected`, `public`, `requiresQuotes`, `static`.
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`.
- `class` - matches any class declaration.
Expand Down Expand Up @@ -262,7 +265,10 @@ Group Selectors are provided for convenience, and essentially bundle up sets of
- `default` - matches everything.
- Allowed `modifiers`: all modifiers.
- Allowed `types`: none.
- `memberLike` - matches the same as `accessor`, `enumMember`, `method`, `parameterProperty`, `property`.
- `accessor` - matches the same as `classicAccessor` and `autoAccessor`.
- Allowed `modifiers`: `abstract`, `override`, `private`, `protected`, `public`, `requiresQuotes`, `static`.
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`.
- `memberLike` - matches the same as `classicAccessor`, `autoAccessor`, `enumMember`, `method`, `parameterProperty`, `property`.
- Allowed `modifiers`: `abstract`, `async`, `override`, `#private`, `private`, `protected`, `public`, `readonly`, `requiresQuotes`, `static`.
- Allowed `types`: none.
- `method` - matches the same as `classMethod`, `objectLiteralMethod`, `typeMethod`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,21 @@ enum Selectors {

// memberLike
parameterProperty = 1 << 3,
accessor = 1 << 4,
classicAccessor = 1 << 4,
enumMember = 1 << 5,
classMethod = 1 << 6,
objectLiteralMethod = 1 << 7,
typeMethod = 1 << 8,
classProperty = 1 << 9,
objectLiteralProperty = 1 << 10,
typeProperty = 1 << 11,
autoAccessor = 1 << 12,

// typeLike
class = 1 << 12,
interface = 1 << 13,
typeAlias = 1 << 14,
enum = 1 << 15,
class = 1 << 13,
interface = 1 << 14,
typeAlias = 1 << 15,
enum = 1 << 16,
typeParameter = 1 << 17,

// other
Expand All @@ -65,7 +66,8 @@ enum MetaSelectors {
Selectors.classMethod |
Selectors.objectLiteralMethod |
Selectors.typeMethod |
Selectors.accessor,
Selectors.classicAccessor |
Selectors.autoAccessor,
typeLike = 0 |
Selectors.class |
Selectors.interface |
Expand All @@ -80,6 +82,7 @@ enum MetaSelectors {
Selectors.classProperty |
Selectors.objectLiteralProperty |
Selectors.typeProperty,
accessor = 0 | Selectors.classicAccessor | Selectors.autoAccessor,
/* eslint-enable @typescript-eslint/prefer-literal-enum-member */
}
type MetaSelectorsString = keyof typeof MetaSelectors;
Expand Down
18 changes: 18 additions & 0 deletions packages/eslint-plugin/src/rules/naming-convention-utils/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,24 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
'override',
'async',
]),
...selectorSchema('classicAccessor', true, [
'abstract',
'private',
'protected',
'public',
'requiresQuotes',
'static',
'override',
]),
...selectorSchema('autoAccessor', true, [
'abstract',
'private',
'protected',
'public',
'requiresQuotes',
'static',
'override',
]),
...selectorSchema('accessor', true, [
'abstract',
'private',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ const SelectorsAllowedToHaveTypes =
Selectors.objectLiteralProperty |
Selectors.typeProperty |
Selectors.parameterProperty |
Selectors.accessor;
Selectors.classicAccessor;

function isCorrectType(
node: TSESTree.Node,
Expand Down
52 changes: 38 additions & 14 deletions packages/eslint-plugin/src/rules/naming-convention.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ export default createRule<Options, MessageIds>({
| TSESTree.TSAbstractMethodDefinitionNonComputedName
| TSESTree.TSAbstractPropertyDefinitionNonComputedName
| TSESTree.TSMethodSignatureNonComputedName
| TSESTree.TSPropertySignatureNonComputedName,
| TSESTree.TSPropertySignatureNonComputedName
| TSESTree.AccessorPropertyNonComputedName,
modifiers: Set<Modifiers>,
): void {
const key = node.key;
Expand All @@ -126,7 +127,9 @@ export default createRule<Options, MessageIds>({
| TSESTree.PropertyDefinition
| TSESTree.TSAbstractMethodDefinition
| TSESTree.TSAbstractPropertyDefinition
| TSESTree.TSParameterProperty,
| TSESTree.TSParameterProperty
| TSESTree.AccessorProperty
| TSESTree.TSAbstractAccessorProperty,
): Set<Modifiers> {
const modifiers = new Set<Modifiers>();
if ('key' in node && node.key.type === AST_NODE_TYPES.PrivateIdentifier) {
Expand All @@ -147,7 +150,8 @@ export default createRule<Options, MessageIds>({
}
if (
node.type === AST_NODE_TYPES.TSAbstractPropertyDefinition ||
node.type === AST_NODE_TYPES.TSAbstractMethodDefinition
node.type === AST_NODE_TYPES.TSAbstractMethodDefinition ||
node.type === AST_NODE_TYPES.TSAbstractAccessorProperty
) {
modifiers.add(Modifiers.abstract);
}
Expand Down Expand Up @@ -519,27 +523,47 @@ export default createRule<Options, MessageIds>({
// #region accessor

'Property[computed = false]:matches([kind = "get"], [kind = "set"])': {
validator: validators.accessor,
validator: validators.classicAccessor,
handler: (node: TSESTree.PropertyNonComputedName, validator): void => {
const modifiers = new Set<Modifiers>([Modifiers.public]);
handleMember(validator, node, modifiers);
},
},

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

// #endregion accessor

// #region autoAccessor

[[
AST_NODE_TYPES.AccessorProperty,
AST_NODE_TYPES.TSAbstractAccessorProperty,
].join(', ')]: {
validator: validators.autoAccessor,
handler: (
node: TSESTree.AccessorPropertyNonComputedName,
validator,
): void => {
const modifiers = getMemberModifiers(node);
handleMember(validator, node, modifiers);
},
},

// #endregion autoAccessor

// #region enumMember

// computed is optional, so can't do [computed = false]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@ import { createTestCases } from './createTestCases';
createTestCases([
{
code: [
'class Ignored { accessor % = 10; }',
'class Ignored { accessor #% = 10; }',
'class Ignored { static accessor % = 10; }',
'class Ignored { static accessor #% = 10; }',
'class Ignored { private accessor % = 10; }',
'class Ignored { private static accessor % = 10; }',
'class Ignored { override accessor % = 10; }',
'class Ignored { accessor "%" = 10; }',
'class Ignored { protected accessor % = 10; }',
'class Ignored { public accessor % = 10; }',
'class Ignored { abstract accessor %; }',
'const ignored = { get %() {} };',
'const ignored = { set "%"(ignored) {} };',
'class Ignored { private get %() {} }',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { createTestCases } from './createTestCases';

createTestCases([
{
code: [
'class Ignored { accessor % = 10; }',
'class Ignored { accessor #% = 10; }',
'class Ignored { static accessor % = 10; }',
'class Ignored { static accessor #% = 10; }',
'class Ignored { private accessor % = 10; }',
'class Ignored { private static accessor % = 10; }',
'class Ignored { override accessor % = 10; }',
'class Ignored { accessor "%" = 10; }',
'class Ignored { protected accessor % = 10; }',
'class Ignored { public accessor % = 10; }',
'class Ignored { abstract accessor %; }',
],
options: {
selector: 'autoAccessor',
},
},
]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { createTestCases } from './createTestCases';

createTestCases([
{
code: [
'const ignored = { get %() {} };',
'const ignored = { set "%"(ignored) {} };',
'class Ignored { private get %() {} }',
'class Ignored { private set "%"(ignored) {} }',
'class Ignored { private static get %() {} }',
'class Ignored { static get #%() {} }',
'abstract class Ignored { abstract get %(): number }',
'abstract class Ignored { abstract set %(ignored: number) }',
],
options: {
selector: 'classicAccessor',
},
},
]);
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,8 @@ export function createTestCases(cases: Cases): void {
selector !== 'memberLike' &&
selector !== 'typeLike' &&
selector !== 'property' &&
selector !== 'method'
selector !== 'method' &&
selector !== 'accessor'
? {
data: {
type: selectorTypeToMessageString(selector),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2088,15 +2088,15 @@ ruleTester.run('naming-convention', rule, {
{
messageId: 'doesNotMatchFormat',
data: {
type: 'Accessor',
type: 'Classic Accessor',
name: 'someGetterOverride',
formats: 'snake_case',
},
},
{
messageId: 'doesNotMatchFormat',
data: {
type: 'Accessor',
type: 'Classic Accessor',
name: 'someSetterOverride',
formats: 'snake_case',
},
Expand Down

0 comments on commit f7198db

Please sign in to comment.