8000 feat(eslint-plugin): [member-ordering] add option to sort case insens… · FDIM/typescript-eslint@e3533d5 · GitHub
[go: up one dir, main page]

Skip to content

Commit e3533d5

Browse files
authored
feat(eslint-plugin): [member-ordering] add option to sort case insensitive (typescript-eslint#3896)
* feat(eslint-plugin): member ordering - case insensitive order option * feat(eslint-plugin): member ordering - add lower/upper ordering invalid test cases * feat(eslint-plugin): member ordering - remove default value for param as it is not used * feat(eslint-plugin): member ordering - fix jsdoc typo * feat(eslint-plugin): member ordering - change 'alphabetically-ci' to 'alphabetically-case-insensitive' * feat(eslint-plugin): member ordering - reduce tests to simply test ordering
1 parent 5a4ce6a commit e3533d5

File tree

5 files changed

+3376
-2629
lines changed

5 files changed

+3376
-2629
lines changed

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

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ These options allow to specify how to group the members and sort their groups.
2626
type TypeOptions<T> =
2727
| {
2828
memberTypes: Array<T> | 'never',
29-
order?: 'alphabetically' | 'as-written',
29+
order?: 'alphabetically' | 'alphabetically-case-insensitive' | 'as-written',
3030
}
3131
| {
32-
order: 'alphabetically',
32+
order: 'alphabetically' | 'alphabetically-case-insensitive' | 'as-written',
3333
};
3434

3535
{
@@ -956,21 +956,21 @@ It is possible to sort all members within a group alphabetically.
956956

957957
#### Configuration: `{ "default": { "memberTypes": <Default Order>, "order": "alphabetically" } }`
958958

959-
This will apply the default order (see above) and enforce an alphabetic order within each group.
959+
This will apply the default order (see above) and enforce an alphabetic case-sensitive order within each group.
960960

961961
##### Incorrect examples
962962

963963
```ts
964964
interface Foo {
965+
B: x;
965966
a: x;
966-
b: x;
967967
c: x;
968968

969969
new (): Bar;
970970
(): Baz;
971971

972+
B(): void;
972973
a(): void;
973-
b(): void;
974974
c(): void;
975975

976976
// Wrong group order, should be placed before all field definitions
@@ -982,16 +982,16 @@ interface Foo {
982982
interface Foo {
983983
[a: string]: number;
984984

985+
B: x;
985986
a: x;
986-
b: x;
987987
c: x;
988988

989989
new (): Bar;
990990
(): Baz;
991991

992992
// Wrong alphabetic order within group
993993
c(): void;
994-
b(): void;
994+
B(): void;
995995
a(): void;
996996
}
997997
```
@@ -1017,6 +1017,73 @@ interface Foo {
10171017

10181018
Note: Wrong alphabetic order `b(): void` should come after `a: b`.
10191019

1020+
### Sorting alphabetically case-insensitive within member groups
1021+
1022+
It is possible to sort all members within a group alphabetically with case insensitivity.
1023+
1024+
#### Configuration: `{ "default": { "memberTypes": <Default Order>, "order": "alphabetically-case-insensitive" } }`
1025+
1026+
This will apply the default order (see above) and enforce an alphabetic case-insensitive order within each group.
1027+
1028+
##### Incorrect examples
1029+
1030+
```ts
1031+
interface Foo {
1032+
a: x;
1033+
B: x;
1034+
c: x;
1035+
1036+
new (): Bar;
1037+
(): Baz;
1038+
1039+
a(): void;
1040+
b(): void;
1041+
C(): void;
1042+
1043+
// Wrong group order, should be placed before all field definitions
1044+
[a: string]: number;
1045+
}
1046+
```
1047+
1048+
```ts
1049+
interface Foo {
1050+
[a: string]: number;
1051+
1052+
a: x;
1053+
B: x;
1054+
c: x;
1055+
1056+
new (): Bar;
1057+
(): Baz;
1058+
1059+
// Wrong alphabetic order within group
1060+
C(): void;
1061+
b(): void;
1062+
a(): void;
1063+
}
1064+
```
1065+
1066+
### Sorting alphabetically case-insensitive while ignoring member groups
1067+
1068+
It is also possible to sort all members with case insensitivity and ignore the member groups completely.
1069+
1070+
#### Configuration: `{ "default": { "memberTypes": "never", "order": "alphabetically-case-insensitive" } }`
1071+
1072+
##### Incorrect example
1073+
1074+
```ts
1075+
interface Foo {
1076+
B(): void;
1077+
a: number;
1078+
1079+
[a: string]: number; // Order doesn't matter (no sortable identifier)
1080+
new (): Bar; // Order doesn't matter (no sortable identifier)
1081+
(): Baz; // Order doesn't matter (no sortable identifier)
1082+
}
1083+
```
1084+
1085+
Note: Wrong alphabetic order `B(): void` should come after `a: number`.
1086+
10201087
## When Not To Use It
10211088

10221089
If you don't care about the general structure of your classes and interfaces, then you will not need this rule.

packages/eslint-plugin/src/rules/member-ordering.ts

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,14 @@ import * as util from '../util';
88

99
export type MessageIds = 'incorrectGroupOrder' | 'incorrectOrder';
1010

11+
type Order =
12+
| 'alphabetically'
13+
| 'alphabetically-case-insensitive'
14+
| 'as-written';
15+
1116
interface SortedOrderConfig {
1217
memberTypes?: string[] | 'never';
13-
order: 'alphabetically' | 'as-written';
18+
order: Order;
1419
}
1520

1621
type OrderConfig = string[] | SortedOrderConfig | 'never';
@@ -46,7 +51,7 @@ const objectConfig = (memberTypes: string[]): JSONSchema.JSONSchema4 => ({
4651
},
4752
order: {
4853
type: 'string',
49-
enum: ['alphabetically', 'as-written'],
54+
enum: ['alphabetically', 'alphabetically-case-insensitive', 'as-written'],
5055
},
5156
},
5257
additionalProperties: false,
@@ -539,10 +544,14 @@ export default util.createRule<Options, MessageIds>({
539544
* Checks if the members are alphabetically sorted.
540545
*
541546
* @param members Members to be validated.
547+
* @param caseSensitive indicates if the alpha ordering is case sensitive or not.
542548
*
543549
* @return True if all members are correctly sorted.
544550
*/
545-
function checkAlphaSort(members: Member[]): boolean {
551+
function checkAlphaSort(
552+
members: Member[],
553+
caseSensitive: boolean,
554+
): boolean {
546555
let previousName = '';
547556
let isCorrectlySorted = true;
548557

@@ -552,7 +561,11 @@ export default util.createRule<Options, MessageIds>({
552561

553562
// Note: Not all members have names
554563
if (name) {
555-
if (name < previousName) {
564+
if (
565+
caseSensitive
566+
? name < previousName
567+
: name.toLowerCase() < previousName.toLowerCase()
568+
) {
556569
context.report({
557570
node: member,
558571
messageId: 'incorrectOrder',
@@ -589,7 +602,7 @@ export default util.createRule<Options, MessageIds>({
589602
}
590603

591604
// Standardize config
592-
let order = null;
605+
let order: Order | null = null;
593606
let memberTypes;
594607

595608
if (Array.isArray(orderConfig)) {
@@ -599,6 +612,10 @@ export default util.createRule<Options, MessageIds>({
599612
memberTypes = orderConfig.memberTypes;
600613
}
601614

615+
const hasAlphaSort = order?.startsWith('alphabetically');
616+
const alphaSortIsCaseSensitive =
617+
order !== 'alphabetically-case-insensitive';
618+
602619
// Check order
603620
if (Array.isArray(memberTypes)) {
604621
const grouped = checkGroupSort(members, memberTypes, supportsModifiers);
@@ -607,11 +624,14 @@ export default util.createRule<Options, MessageIds>({
607624
return;
608625
}
609626

610-
if (order === 'alphabetically') {
611-
grouped.some(groupMember => !checkAlphaSort(groupMember));
627+
if (hasAlphaSort) {
628+
grouped.some(
629+
groupMember =>
630+
!checkAlphaSort(groupMember, alphaSortIsCaseSensitive),
631+
);
612632
}
613-
} else if (order === 'alphabetically') {
614-
checkAlphaSort(members);
633+
} else if (hasAlphaSort) {
634+
checkAlphaSort(members, alphaSortIsCaseSensitive);
615635
}
616636
}
617637

0 commit comments

Comments
 (0)
0