Skip to content

Commit a08cb93

Browse files
akulsr0ljharb
authored andcommitted
[Fix] sort-prop-types: single line type ending without semicolon
1 parent 4b3209b commit a08cb93

File tree

4 files changed

+75
-6
lines changed

4 files changed

+75
-6
lines changed

CHANGELOG.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,14 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
1515
* [`jsx-closing-tag-location`]: add `line-aligned` option ([#3777] @kimtaejin3)
1616
* [`no-danger`]: add `customComponentNames` option ([#3748][] @akulsr0)
1717

18+
### Fixed
19+
* [`no-invalid-html-attribute`]: substitute placeholders in suggestion messages ([#3759][] @mdjermanovic)
20+
* [`sort-prop-types`]: single line type ending without semicolon ([#3784][] @akulsr0)
21+
1822
### Changed
1923
* [Refactor] `variableUtil`: Avoid creating a single flat variable scope for each lookup ([#3782][] @DanielRosenwasser)
2024

25+
[#3784]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3784
2126
[#3782]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3782
2227
[#3777]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3777
2328
[#3774]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3774
@@ -28,9 +33,6 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
2833
[#3724]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3724
2934
[#3694]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3694
3035

31-
### Fixed
32-
* [`no-invalid-html-attribute`]: substitute placeholders in suggestion messages ([#3759][] @mdjermanovic)
33-
3436
## [7.34.4] - 2024.07.13
3537

3638
### Fixed

lib/rules/sort-prop-types.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ module.exports = {
129129
requiredFirst,
130130
callbacksLast,
131131
noSortAlphabetically,
132-
sortShapeProp
132+
sortShapeProp,
133+
checkTypes
133134
);
134135
}
135136

lib/util/propTypesSort.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ const commentnodeMap = new WeakMap(); // all nodes reference WeakMap for start a
126126
* @param {Boolean=} callbacksLast whether or not to sort callbacks after everything else.
127127
* @param {Boolean=} noSortAlphabetically whether or not to disable alphabetical sorting of the elements.
128128
* @param {Boolean=} sortShapeProp whether or not to sort propTypes defined in PropTypes.shape.
129+
* @param {Boolean=} checkTypes whether or not sorting of prop type definitions are checked.
129130
* @returns {Object|*|{range, text}} the sort order of the two elements.
130131
*/
131132
function fixPropTypesSort(
@@ -136,7 +137,8 @@ function fixPropTypesSort(
136137
requiredFirst,
137138
callbacksLast,
138139
noSortAlphabetically,
139-
sortShapeProp
140+
sortShapeProp,
141+
checkTypes
140142
) {
141143
function sortInSource(allNodes, source) {
142144
const originalSource = source;
@@ -183,10 +185,15 @@ function fixPropTypesSort(
183185
);
184186

185187
const sourceCodeText = getText(context);
188+
let separator = '';
186189
source = nodes.reduceRight((acc, attr, index) => {
187190
const sortedAttr = sortedAttributes[index];
188191
const commentNode = commentnodeMap.get(sortedAttr);
189192
let sortedAttrText = sourceCodeText.slice(commentNode.start, commentNode.end);
193+
const sortedAttrTextLastChar = sortedAttrText[sortedAttrText.length - 1];
194+
if (!separator && [';', ','].some((allowedSep) => sortedAttrTextLastChar === allowedSep)) {
195+
separator = sortedAttrTextLastChar;
196+
}
190197
if (sortShapeProp && isShapeProp(sortedAttr.value)) {
191198
const shape = getShapeProperties(sortedAttr.value);
192199
if (shape) {
@@ -197,7 +204,8 @@ function fixPropTypesSort(
197204
sortedAttrText = attrSource.slice(sortedAttr.range[0], sortedAttr.range[1]);
198205
}
199206
}
200-
return `${acc.slice(0, commentnodeMap.get(attr).start)}${sortedAttrText}${acc.slice(commentnodeMap.get(attr).end)}`;
207+
const sortedAttrTextVal = checkTypes && !sortedAttrText.endsWith(separator) ? `${sortedAttrText}${separator}` : sortedAttrText;
208+
return `${acc.slice(0, commentnodeMap.get(attr).start)}${sortedAttrTextVal}${acc.slice(commentnodeMap.get(attr).end)}`;
201209
}, source);
202210
});
203211
return source;

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

+58
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,18 @@ ruleTester.run('sort-prop-types', rule, {
501501
}
502502
`,
503503
options: [{ checkTypes: true }],
504+
},
505+
{
506+
code: `
507+
const Foo = (props: {
508+
aaa: string,
509+
zzz: string
510+
}) => {
511+
return null;
512+
}
513+
`,
514+
features: ['types'],
515+
options: [{ checkTypes: true }],
504516
}
505517
)),
506518
invalid: parsers.all([].concat(
@@ -2356,6 +2368,52 @@ ruleTester.run('sort-prop-types', rule, {
23562368
column: 11,
23572369
},
23582370
],
2371+
},
2372+
{
2373+
code: `
2374+
type CustomProps = { onChange: () => void; name: string };
2375+
const Foo = (props: CustomProps) => {
2376+
return null;
2377+
}
2378+
`,
2379+
output: `
2380+
type CustomProps = { name: string; onChange: () => void };
2381+
const Foo = (props: CustomProps) => {
2382+
return null;
2383+
}
2384+
`,
2385+
features: ['types'],
2386+
options: [{ checkTypes: true }],
2387+
errors: [
2388+
{
2389+
messageId: 'propsNotSorted',
2390+
line: 2,
2391+
column: 52,
2392+
},
2393+
],
2394+
},
2395+
{
2396+
code: `
2397+
type CustomProps = { onChange: (event: { target: { name: string; value: string } }) => void; name: string };
2398+
const Foo = (props: CustomProps) => {
2399+
return null;
2400+
}
2401+
`,
2402+
output: `
2403+
type CustomProps = { name: string; onChange: (event: { target: { name: string; value: string } }) => void };
2404+
const Foo = (props: CustomProps) => {
2405+
return null;
2406+
}
2407+
`,
2408+
features: ['types'],
2409+
options: [{ checkTypes: true }],
2410+
errors: [
2411+
{
2412+
messageId: 'propsNotSorted',
2413+
line: 2,
2414+
column: 102,
2415+
},
2416+
],
23592417
}
23602418
)),
23612419
});

0 commit comments

Comments
 (0)