Skip to content

Commit

Permalink
feat(eslint-plugin): [member-ordering] support static blocks (#5417)
Browse files Browse the repository at this point in the history
* feat(eslint-plugin): [member-ordering] support static blocks

* Update packages/eslint-plugin/docs/rules/member-ordering.md

Co-authored-by: Josh Goldberg <me@joshuakgoldberg.com>

* Add some tests

Co-authored-by: Josh Goldberg <me@joshuakgoldberg.com>
  • Loading branch information
Josh-Cena and JoshuaKGoldberg committed Aug 6, 2022
1 parent d2394f8 commit 5983e5a
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 10 deletions.
33 changes: 27 additions & 6 deletions packages/eslint-plugin/docs/rules/member-ordering.md
Expand Up @@ -94,6 +94,9 @@ The default configuration looks as follows:

"field",

// Static initialization
"static-initialization",

// Constructors
"public-constructor",
"protected-constructor",
Expand Down Expand Up @@ -908,6 +911,9 @@ The most explicit and granular form is the following:
"protected-abstract-field",
"private-abstract-field",

// Static initialization
"static-initialization",

// Constructors
"public-constructor",
"protected-constructor",
Expand Down Expand Up @@ -1006,6 +1012,9 @@ It is also possible to group member types by their accessibility (`static`, `ins
"protected-field", // = ["protected-static-field", "protected-instance-field"]
"private-field", // = ["private-static-field", "private-instance-field"]

// Static initialization
// No accessibility for static initialization.

// Constructors
// Only the accessibility of constructors is configurable. See below.

Expand Down Expand Up @@ -1043,6 +1052,9 @@ their accessibility.

"decorated-field", // = ["public-decorated-field", "protected-decorated-field", "private-decorated-field"]

// Static initialization
// No decorators for static initialization.

// Constructors
// There are no decorators for constructors.

Expand All @@ -1051,14 +1063,14 @@ their accessibility.
"protected-decorated-get",
"private-decorated-get",

"decorated-get" // = ["public-decorated-get", "protected-decorated-get", "private-decorated-get"]
"decorated-get", // = ["public-decorated-get", "protected-decorated-get", "private-decorated-get"]

// Setters
"public-decorated-set",
"protected-decorated-set",
"private-decorated-set",

"decorated-set" // = ["public-decorated-set", "protected-decorated-set", "private-decorated-set"]
"decorated-set", // = ["public-decorated-set", "protected-decorated-set", "private-decorated-set"]

// Methods
"public-decorated-method",
Expand All @@ -1083,18 +1095,21 @@ Another option is to group the member types by their scope (`public`, `protected
"instance-field", // = ["public-instance-field", "protected-instance-field", "private-instance-field"]
"abstract-field", // = ["public-abstract-field", "protected-abstract-field", "private-abstract-field"]

// Static initialization
// No scope for static initialization.

// Constructors
"constructor", // = ["public-constructor", "protected-constructor", "private-constructor"]

// Getters
"static-get", // = ["public-static-get", "protected-static-get", "private-static-get"]
"instance-get", // = ["public-instance-get", "protected-instance-get", "private-instance-get"]
"abstract-get" // = ["public-abstract-get", "protected-abstract-get", "private-abstract-get"]
"abstract-get", // = ["public-abstract-get", "protected-abstract-get", "private-abstract-get"]

// Setters
"static-set", // = ["public-static-set", "protected-static-set", "private-static-set"]
"instance-set", // = ["public-instance-set", "protected-instance-set", "private-instance-set"]
"abstract-set" // = ["public-abstract-set", "protected-abstract-set", "private-abstract-set"]
"abstract-set", // = ["public-abstract-set", "protected-abstract-set", "private-abstract-set"]

// Methods
"static-method", // = ["public-static-method", "protected-static-method", "private-static-method"]
Expand All @@ -1116,15 +1131,18 @@ The third grouping option is to ignore both scope and accessibility.
"field", // = ["public-static-field", "protected-static-field", "private-static-field", "public-instance-field", "protected-instance-field", "private-instance-field",
// "public-abstract-field", "protected-abstract-field", private-abstract-field"]

// Static initialization
// No grouping for static initialization.

// Constructors
// Only the accessibility of constructors is configurable.

// Getters
"get" // = ["public-static-get", "protected-static-get", "private-static-get", "public-instance-get", "protected-instance-get", "private-instance-get",
"get", // = ["public-static-get", "protected-static-get", "private-static-get", "public-instance-get", "protected-instance-get", "private-instance-get",
// "public-abstract-get", "protected-abstract-get", "private-abstract-get"]

// Setters
"set" // = ["public-static-set", "protected-static-set", "private-static-set", "public-instance-set", "protected-instance-set", "private-instance-set",
"set", // = ["public-static-set", "protected-static-set", "private-static-set", "public-instance-set", "protected-instance-set", "private-instance-set",
// "public-abstract-set", "protected-abstract-set", "private-abstract-set"]

// Methods
Expand All @@ -1145,6 +1163,9 @@ It is also possible to group different member types at the same rank.
// Fields
"field",

// Static initialization
"static-initialization",

// Constructors
"constructor",

Expand Down
20 changes: 16 additions & 4 deletions packages/eslint-plugin/src/rules/member-ordering.ts
Expand Up @@ -15,7 +15,8 @@ type MemberKind =
| 'get'
| 'method'
| 'set'
| 'signature';
| 'signature'
| 'static-initialization';

type DecoratedMemberKind = 'field' | 'method' | 'get' | 'set';

Expand All @@ -25,7 +26,10 @@ type MemberScope = 'static' | 'instance' | 'abstract';

type BaseMemberType =
| MemberKind
| `${TSESTree.Accessibility}-${Exclude<MemberKind, 'signature'>}`
| `${TSESTree.Accessibility}-${Exclude<
MemberKind,
'signature' | 'static-initialization'
>}`
| `${TSESTree.Accessibility}-decorated-${DecoratedMemberKind}`
| `decorated-${DecoratedMemberKind}`
| `${TSESTree.Accessibility}-${MemberScope}-${NonCallableMemberKind}`
Expand Down Expand Up @@ -126,6 +130,9 @@ export const defaultOrder: MemberType[] = [

'field',

// Static initialization
'static-initialization',

// Constructors
'public-constructor',
'protected-constructor',
Expand Down Expand Up @@ -231,12 +238,13 @@ const allMemberTypes = Array.from(
'constructor',
'get',
'set',
'static-initialization',
] as const
).reduce<Set<MemberType>>((all, type) => {
all.add(type);

(['public', 'protected', 'private'] as const).forEach(accessibility => {
if (type !== 'signature') {
if (type !== 'signature' && type !== 'static-initialization') {
all.add(`${accessibility}-${type}`); // e.g. `public-field`
}

Expand Down Expand Up @@ -295,6 +303,8 @@ function getNodeType(node: Member): MemberKind | null {
return 'field';
case AST_NODE_TYPES.TSIndexSignature:
return 'signature';
case AST_NODE_TYPES.StaticBlock:
return 'static-initialization';
default:
return null;
}
Expand Down Expand Up @@ -352,6 +362,8 @@ function getMemberName(
return 'call';
case AST_NODE_TYPES.TSIndexSignature:
return util.getNameFromIndexSignature(node);
case AST_NODE_TYPES.StaticBlock:
return 'static block';
default:
return null;
}
Expand Down Expand Up @@ -438,7 +450,7 @@ function getRank(
memberGroups.push(`decorated-${type}`);
}

if (type !== 'signature') {
if (type !== 'signature' && type !== 'static-initialization') {
if (type !== 'constructor') {
// Constructors have no scope
memberGroups.push(`${accessibility}-${scope}-${type}`);
Expand Down
Expand Up @@ -493,6 +493,24 @@ const foo = class Foo {
},
],
},

// default option + static blocks; should always be valid
{
code: `
class Foo {
static {}
static {}
}
`,
options: [
{
default: {
memberTypes: 'never',
order: 'alphabetically-case-insensitive',
},
},
],
},
],
invalid: [
// default option + interface + wrong order within group and wrong group order + alphabetically
Expand Down
Expand Up @@ -1701,6 +1701,24 @@ const foo = class Foo {
},
],
},

// default option + static blocks; should always be valid
{
code: `
class Foo {
static {}
static {}
}
`,
options: [
{
default: {
memberTypes: 'never',
order: 'alphabetically',
},
},
],
},
],
invalid: [
// default option + class + wrong order within group and wrong group order + alphabetically
Expand Down

0 comments on commit 5983e5a

Please sign in to comment.