Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(eslint-plugin): [member-ordering] support static blocks #5417

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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