Skip to content

Commit

Permalink
fix(eslint-plugin): [member-ordering] report alphabetical sorting for…
Browse files Browse the repository at this point in the history
… all groups instead of just the first failing group (#8263)

* chore: report alphabetical sorting for all groups

fixes: #8100

* chore: lint errors

* chore: address reviews

* chore: small miss

* chore: lint errors

* chore: small refactor

* chore: lint error

* chore: update jsdoc comment

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

* chore: address reviews

* chore: small miss

* chore: last prettier write

---------

Co-authored-by: Josh Goldberg ✨ <git@joshuakgoldberg.com>
  • Loading branch information
arka1002 and JoshuaKGoldberg committed Mar 6, 2024
1 parent 3ac824b commit c06ce1a
Show file tree
Hide file tree
Showing 5 changed files with 274 additions and 4 deletions.
76 changes: 72 additions & 4 deletions packages/eslint-plugin/src/rules/member-ordering.ts
Expand Up @@ -615,6 +615,59 @@ function getRank(
return getRankOrder(memberGroups, orderConfig);
}

/**
* Groups members into arrays of consecutive members with the same rank.
* If, for example, the memberSet parameter looks like the following...
* @example
* ```
* interface Foo {
* [a: string]: number;
*
* a: x;
* B: x;
* c: x;
*
* c(): void;
* B(): void;
* a(): void;
*
* (): Baz;
*
* new (): Bar;
* }
* ```
* ...the resulting array will look like: [[a, B, c], [c, B, a]].
* @param memberSet The members to be grouped.
* @param memberType The configured order of member types.
* @param supportsModifiers It'll get passed to getRank().
* @returns The array of groups of members.
*/
function groupMembersByType(
members: Member[],
memberTypes: MemberType[],
supportsModifiers: boolean,
): Member[][] {
const groupedMembers: Member[][] = [];
const memberRanks = members.map(member =>
getRank(member, memberTypes, supportsModifiers),
);
let previousRank: number | undefined = undefined;
members.forEach((member, index) => {
if (index === members.length - 1) {
return;
}
const rankOfCurrentMember = memberRanks[index];
const rankOfNextMember = memberRanks[index + 1];
if (rankOfCurrentMember === previousRank) {
groupedMembers.at(-1)?.push(member);
} else if (rankOfCurrentMember === rankOfNextMember) {
groupedMembers.push([member]);
previousRank = rankOfCurrentMember;
}
});
return groupedMembers;
}

/**
* Gets the lowest possible rank(s) higher than target.
* e.g. given the following order:
Expand Down Expand Up @@ -936,6 +989,21 @@ export default createRule<Options, MessageIds>({
let memberTypes: MemberType[] | string | undefined;
let optionalityOrder: OptionalityOrder | undefined;

/**
* It runs an alphabetic sort on the groups of the members of the class in the source code.
* @param memberSet The members in the class of the source code on which the grouping operation will be performed.
*/
const checkAlphaSortForAllMembers = (memberSet: Member[]): undefined => {
const hasAlphaSort = !!(order && order !== 'as-written');
if (hasAlphaSort && Array.isArray(memberTypes)) {
groupMembersByType(memberSet, memberTypes, supportsModifiers).forEach(
members => {
checkAlphaSort(members, order as AlphabeticalOrder);
},
);
}
};

// returns true if everything is good and false if an error was reported
const checkOrder = (memberSet: Member[]): boolean => {
const hasAlphaSort = !!(order && order !== 'as-written');
Expand All @@ -949,20 +1017,20 @@ export default createRule<Options, MessageIds>({
);

if (grouped == null) {
checkAlphaSortForAllMembers(members);
return false;
}

if (hasAlphaSort) {
return !grouped.some(
groupMember =>
!checkAlphaSort(groupMember, order as AlphabeticalOrder),
grouped.map(groupMember =>
checkAlphaSort(groupMember, order as AlphabeticalOrder),
);
}
} else if (hasAlphaSort) {
return checkAlphaSort(memberSet, order as AlphabeticalOrder);
}

return true;
return false;
};

if (Array.isArray(orderConfig)) {
Expand Down
Expand Up @@ -539,6 +539,20 @@ interface Foo {
},
],
errors: [
{
messageId: 'incorrectOrder',
data: {
member: 'B',
beforeMember: 'c',
},
},
{
messageId: 'incorrectOrder',
data: {
member: 'a',
beforeMember: 'B',
},
},
{
messageId: 'incorrectGroupOrder',
data: {
Expand Down Expand Up @@ -584,6 +598,20 @@ type Foo = {
},
],
errors: [
{
messageId: 'incorrectOrder',
data: {
member: 'B',
beforeMember: 'c',
},
},
{
messageId: 'incorrectOrder',
data: {
member: 'a',
beforeMember: 'B',
},
},
{
messageId: 'incorrectGroupOrder',
data: {
Expand Down Expand Up @@ -623,6 +651,20 @@ class Foo {
},
],
errors: [
{
messageId: 'incorrectOrder',
data: {
member: 'B',
beforeMember: 'c',
},
},
{
messageId: 'incorrectOrder',
data: {
member: 'a',
beforeMember: 'B',
},
},
{
messageId: 'incorrectGroupOrder',
data: {
Expand Down Expand Up @@ -655,6 +697,20 @@ const foo = class Foo {
},
],
errors: [
{
messageId: 'incorrectOrder',
data: {
member: 'B',
beforeMember: 'c',
},
},
{
messageId: 'incorrectOrder',
data: {
member: 'a',
beforeMember: 'B',
},
},
{
messageId: 'incorrectGroupOrder',
data: {
Expand Down
Expand Up @@ -1853,6 +1853,20 @@ interface Foo {
{ default: { memberTypes: defaultOrder, order: 'alphabetically' } },
],
errors: [
{
messageId: 'incorrectOrder',
data: {
member: 'b',
beforeMember: 'c',
},
},
{
messageId: 'incorrectOrder',
data: {
member: 'a',
beforeMember: 'b',
},
},
{
messageId: 'incorrectGroupOrder',
data: {
Expand Down Expand Up @@ -1893,6 +1907,20 @@ type Foo = {
{ default: { memberTypes: defaultOrder, order: 'alphabetically' } },
],
errors: [
{
messageId: 'incorrectOrder',
data: {
member: 'b',
beforeMember: 'c',
},
},
{
messageId: 'incorrectOrder',
data: {
member: 'a',
beforeMember: 'b',
},
},
{
messageId: 'incorrectGroupOrder',
data: {
Expand Down Expand Up @@ -1927,6 +1955,20 @@ class Foo {
{ default: { memberTypes: defaultOrder, order: 'alphabetically' } },
],
errors: [
{
messageId: 'incorrectOrder',
data: {
member: 'b',
beforeMember: 'c',
},
},
{
messageId: 'incorrectOrder',
data: {
member: 'a',
beforeMember: 'b',
},
},
{
messageId: 'incorrectGroupOrder',
data: {
Expand Down Expand Up @@ -1954,6 +1996,20 @@ const foo = class Foo {
{ default: { memberTypes: defaultOrder, order: 'alphabetically' } },
],
errors: [
{
messageId: 'incorrectOrder',
data: {
member: 'b',
beforeMember: 'c',
},
},
{
messageId: 'incorrectOrder',
data: {
member: 'a',
beforeMember: 'b',
},
},
{
messageId: 'incorrectGroupOrder',
data: {
Expand Down Expand Up @@ -1996,6 +2052,13 @@ class Foo {
},
],
errors: [
{
messageId: 'incorrectOrder',
data: {
member: 'a2',
beforeMember: 'a3',
},
},
{
messageId: 'incorrectGroupOrder',
data: {
Expand Down Expand Up @@ -2142,6 +2205,20 @@ class Foo {
{ default: { memberTypes: defaultOrder, order: 'alphabetically' } },
],
errors: [
{
messageId: 'incorrectOrder',
data: {
member: 'b',
beforeMember: 'c',
},
},
{
messageId: 'incorrectOrder',
data: {
member: 'a',
beforeMember: 'b',
},
},
{
messageId: 'incorrectGroupOrder',
data: {
Expand Down Expand Up @@ -2287,6 +2364,20 @@ const foo = class Foo {
{ default: { memberTypes: defaultOrder, order: 'alphabetically' } },
],
errors: [
{
messageId: 'incorrectOrder',
data: {
member: 'b',
beforeMember: 'c',
},
},
{
messageId: 'incorrectOrder',
data: {
member: 'a',
beforeMember: 'b',
},
},
{
messageId: 'incorrectGroupOrder',
data: {
Expand Down Expand Up @@ -2440,6 +2531,20 @@ interface Foo {
{ default: { memberTypes: defaultOrder, order: 'alphabetically' } },
],
errors: [
{
messageId: 'incorrectOrder',
data: {
member: 'b',
beforeMember: 'c',
},
},
{
messageId: 'incorrectOrder',
data: {
member: 'a',
beforeMember: 'b',
},
},
{
messageId: 'incorrectGroupOrder',
data: {
Expand Down Expand Up @@ -2600,6 +2705,20 @@ type Foo = {
{ default: { memberTypes: defaultOrder, order: 'alphabetically' } },
],
errors: [
{
messageId: 'incorrectOrder',
data: {
member: 'b',
beforeMember: 'c',
},
},
{
messageId: 'incorrectOrder',
data: {
member: 'a',
beforeMember: 'b',
},
},
{
messageId: 'incorrectGroupOrder',
data: {
Expand Down
Expand Up @@ -122,6 +122,15 @@ interface Example {
line: 10,
messageId: 'incorrectOrder',
},
{
column: 3,
data: {
beforeMember: 'B1',
member: 'a1',
},
line: 15,
messageId: 'incorrectOrder',
},
],
options: [
{
Expand Down

0 comments on commit c06ce1a

Please sign in to comment.