Skip to content

Commit 3c11201

Browse files
caesar1030ljharb
authored andcommitted
[Fix] sort-prop-types: ensure sort-prop-types respects noSortAlphabetically
1 parent 302925b commit 3c11201

File tree

4 files changed

+131
-12
lines changed

4 files changed

+131
-12
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
88
### Fixed
99
* [`require-default-props`]: fix config schema ([#3605][] @controversial)
1010
* [`jsx-curly-brace-presence`]: Revert [#3538][] due to issues with intended string type casting usage ([#3611][] @taozhou-glean)
11+
* [`sort-prop-types`]: ensure sort-prop-types respects noSortAlphabetically ([#3610][] @caesar1030)
1112

1213
[#3611]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3611
14+
[#3610]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3610
1315
[#3605]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3605
1416

1517
## [7.33.0] - 2023.07.19

lib/rules/sort-prop-types.js

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ module.exports = {
114114
ignoreCase,
115115
requiredFirst,
116116
callbacksLast,
117+
noSortAlphabetically,
117118
sortShapeProp
118119
);
119120
}

lib/util/propTypesSort.js

+26-12
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,10 @@ function getShapeProperties(node) {
6969
* @param {Boolean=} ignoreCase whether or not to ignore case when comparing the two elements.
7070
* @param {Boolean=} requiredFirst whether or not to sort required elements first.
7171
* @param {Boolean=} callbacksLast whether or not to sort callbacks after everything else.
72+
* @param {Boolean=} noSortAlphabetically whether or not to disable alphabetical sorting of the elements.
7273
* @returns {Number} the sort order of the two elements.
7374
*/
74-
function sorter(a, b, context, ignoreCase, requiredFirst, callbacksLast) {
75+
function sorter(a, b, context, ignoreCase, requiredFirst, callbacksLast, noSortAlphabetically) {
7576
const aKey = String(astUtil.getKeyValue(context, a));
7677
const bKey = String(astUtil.getKeyValue(context, b));
7778

@@ -93,19 +94,23 @@ function sorter(a, b, context, ignoreCase, requiredFirst, callbacksLast) {
9394
}
9495
}
9596

96-
if (ignoreCase) {
97-
return aKey.localeCompare(bKey);
98-
}
97+
if (!noSortAlphabetically) {
98+
if (ignoreCase) {
99+
return aKey.localeCompare(bKey);
100+
}
99101

100-
if (aKey < bKey) {
101-
return -1;
102-
}
103-
if (aKey > bKey) {
104-
return 1;
102+
if (aKey < bKey) {
103+
return -1;
104+
}
105+
if (aKey > bKey) {
106+
return 1;
107+
}
105108
}
106109
return 0;
107110
}
108111

112+
const commentnodeMap = new WeakMap(); // all nodes reference WeakMap for start and end range
113+
109114
/**
110115
* Fixes sort order of prop types.
111116
*
@@ -115,11 +120,20 @@ function sorter(a, b, context, ignoreCase, requiredFirst, callbacksLast) {
115120
* @param {Boolean=} ignoreCase whether or not to ignore case when comparing the two elements.
116121
* @param {Boolean=} requiredFirst whether or not to sort required elements first.
117122
* @param {Boolean=} callbacksLast whether or not to sort callbacks after everything else.
123+
* @param {Boolean=} noSortAlphabetically whether or not to disable alphabetical sorting of the elements.
118124
* @param {Boolean=} sortShapeProp whether or not to sort propTypes defined in PropTypes.shape.
119125
* @returns {Object|*|{range, text}} the sort order of the two elements.
120126
*/
121-
const commentnodeMap = new WeakMap(); // all nodes reference WeakMap for start and end range
122-
function fixPropTypesSort(fixer, context, declarations, ignoreCase, requiredFirst, callbacksLast, sortShapeProp) {
127+
function fixPropTypesSort(
128+
fixer,
129+
context,
130+
declarations,
131+
ignoreCase,
132+
requiredFirst,
133+
callbacksLast,
134+
noSortAlphabetically,
135+
sortShapeProp
136+
) {
123137
function sortInSource(allNodes, source) {
124138
const originalSource = source;
125139
const sourceCode = context.getSourceCode();
@@ -161,7 +175,7 @@ function fixPropTypesSort(fixer, context, declarations, ignoreCase, requiredFirs
161175
nodeGroups.forEach((nodes) => {
162176
const sortedAttributes = toSorted(
163177
nodes,
164-
(a, b) => sorter(a, b, context, ignoreCase, requiredFirst, callbacksLast)
178+
(a, b) => sorter(a, b, context, ignoreCase, requiredFirst, callbacksLast, noSortAlphabetically)
165179
);
166180

167181
source = nodes.reduceRight((acc, attr, index) => {

tests/lib/rules/sort-prop-types.js

+102
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,19 @@ ruleTester.run('sort-prop-types', rule, {
467467
};
468468
`,
469469
options: [{ sortShapeProp: true }],
470+
},
471+
{
472+
code: `
473+
var Component = createReactClass({
474+
propTypes: {
475+
a: React.PropTypes.string,
476+
c: React.PropTypes.string,
477+
b: React.PropTypes.string,
478+
onChange: React.PropTypes.func,
479+
}
480+
});
481+
`,
482+
options: [{ callbacksLast: true, noSortAlphabetically: true }],
470483
}
471484
)),
472485
invalid: parsers.all([].concat(
@@ -1886,6 +1899,37 @@ ruleTester.run('sort-prop-types', rule, {
18861899
},
18871900
],
18881901
},
1902+
{
1903+
code: `
1904+
var Component = createReactClass({
1905+
propTypes: {
1906+
onChange: React.PropTypes.func,
1907+
a: React.PropTypes.string,
1908+
c: React.PropTypes.string,
1909+
b: React.PropTypes.string,
1910+
}
1911+
});
1912+
`,
1913+
output: `
1914+
var Component = createReactClass({
1915+
propTypes: {
1916+
a: React.PropTypes.string,
1917+
c: React.PropTypes.string,
1918+
b: React.PropTypes.string,
1919+
onChange: React.PropTypes.func,
1920+
}
1921+
});
1922+
`,
1923+
options: [{ callbacksLast: true, noSortAlphabetically: true }],
1924+
errors: [
1925+
{
1926+
messageId: 'callbackPropsLast',
1927+
line: 4,
1928+
column: 13,
1929+
type: 'Property',
1930+
},
1931+
],
1932+
},
18891933
semver.satisfies(eslintPkg.version, '> 3') ? {
18901934
code: `
18911935
var First = createReactClass({
@@ -2148,6 +2192,64 @@ ruleTester.run('sort-prop-types', rule, {
21482192
type: 'Property',
21492193
},
21502194
],
2195+
} : [],
2196+
semver.satisfies(eslintPkg.version, '> 3') ? {
2197+
code: `
2198+
var Component = createReactClass({
2199+
propTypes: {
2200+
/* onChange */ onChange: React.PropTypes.func,
2201+
/* a */ a: React.PropTypes.string,
2202+
/* c */ c: React.PropTypes.string,
2203+
/* b */ b: React.PropTypes.string,
2204+
}
2205+
});
2206+
`,
2207+
output: `
2208+
var Component = createReactClass({
2209+
propTypes: {
2210+
/* a */ a: React.PropTypes.string,
2211+
/* c */ c: React.PropTypes.string,
2212+
/* b */ b: React.PropTypes.string,
2213+
/* onChange */ onChange: React.PropTypes.func,
2214+
}
2215+
});
2216+
`,
2217+
options: [{ callbacksLast: true, noSortAlphabetically: true }],
2218+
errors: [
2219+
{
2220+
messageId: 'callbackPropsLast',
2221+
line: 4,
2222+
},
2223+
],
2224+
} : [],
2225+
semver.satisfies(eslintPkg.version, '> 3') ? {
2226+
code: `
2227+
var Component = createReactClass({
2228+
propTypes: {
2229+
/* onChange */ onChange: React.PropTypes.func /* onChange */,
2230+
/* a */ a: React.PropTypes.string /* a */,
2231+
/* c */ c: React.PropTypes.string /* c */,
2232+
/* b */ b: React.PropTypes.string /* b */,
2233+
}
2234+
});
2235+
`,
2236+
output: `
2237+
var Component = createReactClass({
2238+
propTypes: {
2239+
/* a */ a: React.PropTypes.string /* a */,
2240+
/* c */ c: React.PropTypes.string /* c */,
2241+
/* b */ b: React.PropTypes.string /* b */,
2242+
/* onChange */ onChange: React.PropTypes.func /* onChange */,
2243+
}
2244+
});
2245+
`,
2246+
options: [{ callbacksLast: true, noSortAlphabetically: true }],
2247+
errors: [
2248+
{
2249+
messageId: 'callbackPropsLast',
2250+
line: 4,
2251+
},
2252+
],
21512253
} : []
21522254
)),
21532255
});

0 commit comments

Comments
 (0)