Skip to content

Commit

Permalink
Issue#2366 sorted attributes respects comments
Browse files Browse the repository at this point in the history
  • Loading branch information
ROSSROSALES committed Aug 16, 2022
1 parent b7f388b commit 51ed373
Show file tree
Hide file tree
Showing 2 changed files with 303 additions and 12 deletions.
88 changes: 76 additions & 12 deletions lib/rules/jsx-sort-props.js
Expand Up @@ -6,6 +6,7 @@
'use strict';

const propName = require('jsx-ast-utils/propName');
//const astUtils = require(".node_modules\eslint\lib\rules\utils\ast-utils.js");
const includes = require('array-includes');
const docsUrl = require('../util/docsUrl');
const jsxUtil = require('../util/jsx');
Expand All @@ -28,7 +29,7 @@ const messages = {
listIsEmpty: 'A customized reserved first list must not be empty',
listReservedPropsFirst: 'Reserved props must be listed before all other props',
listCallbacksLast: 'Callbacks must be listed after all other props',
listShorthandFirst: 'Shorthand props must be listed before all other props',
listShorthandFirst: 'S horthand props must be listed before all other props',
listShorthandLast: 'Shorthand props must be listed after all other props',
listMultilineFirst: 'Multiline props must be listed before all other props',
listMultilineLast: 'Multiline props must be listed after all other props',
Expand All @@ -46,6 +47,12 @@ function isReservedPropName(name, list) {
return list.indexOf(name) >= 0;
}

function sorttoend(node) {
if (attributemap.get(node) && attributemap.get(node)[1]){
return true
}
}

function contextCompare(a, b, options) {
let aProp = propName(a);
let bProp = propName(b);
Expand Down Expand Up @@ -98,6 +105,17 @@ function contextCompare(a, b, options) {
return 0;
}

if (options.commentbetween) {
const asorttoend = sorttoend(a);
const bsorttoend = sorttoend(b);
if (asorttoend && !bsorttoend) {
return 1;
}
if (!asorttoend && bsorttoend) {
return -1;
}
}

const actualLocale = options.locale === 'auto' ? undefined : options.locale;

if (options.ignoreCase) {
Expand All @@ -120,24 +138,67 @@ function contextCompare(a, b, options) {
* @param {Array<JSXSpreadAttribute|JSXAttribute>} attributes
* @return {Array<Array<JSXAttribute>>}
*/
function getGroupsOfSortableAttributes(attributes) {

const attributemap = new WeakMap()
// attributemap = [endrange, true||false if comment inbetween nodes exists, it needs to be sorted to end ]
function getGroupsOfSortableAttributes(attributes, context) {
const sortableAttributeGroups = [];
const sourceCode = context.getSourceCode();

let groupCount = 0;
for (let i = 0; i < attributes.length; i++) {
const attribute = attributes[i];
const nextattribute = attributes[i+1];
const attributeline = attribute.loc.start.line;
const comment = sourceCode.getCommentsAfter(attribute);
const lastAttr = attributes[i - 1];
function addtoSortableAttributeGroups() {sortableAttributeGroups[groupCount - 1].push(attribute)};
// If we have no groups or if the last attribute was JSXSpreadAttribute
// then we start a new group. Append attributes to the group until we
// come across another JSXSpreadAttribute or exhaust the array.
if (
!lastAttr
|| (lastAttr.type === 'JSXSpreadAttribute'
&& attributes[i].type !== 'JSXSpreadAttribute')
&& attribute.type !== 'JSXSpreadAttribute')
) {
groupCount += 1;
sortableAttributeGroups[groupCount - 1] = [];
}
if (attributes[i].type !== 'JSXSpreadAttribute') {
sortableAttributeGroups[groupCount - 1].push(attributes[i]);
if (attribute.type !== 'JSXSpreadAttribute') {
if (comment.length > 0) {
const commentline = comment[0].loc.start.line
if (attributeline + 1 == commentline && comment.length == 1 && nextattribute) {
attributemap.set(attribute, [nextattribute.range[1], true])
addtoSortableAttributeGroups()
i++
continue
}
if (attributeline == commentline && comment.length == 1) {
if (comment[0].type == 'Block') {
attributemap.set(attribute, [nextattribute.range[1], true])
addtoSortableAttributeGroups()
i++
continue
}
attributemap.set(attribute, [comment[0].range[1], false])
addtoSortableAttributeGroups()
}
if (comment.length > 1) {
if (attributeline + 1 == comment[1].loc.start.line && nextattribute) {
const commentnextattribute = sourceCode.getCommentsAfter(nextattribute);
attributemap.set(attribute, [nextattribute.range[1], true])
if (commentnextattribute.length == 1 && nextattribute.loc.start.line == commentnextattribute[0].loc.start.line) {
attributemap.set(attribute, [commentnextattribute[0].range[1], true])
}
addtoSortableAttributeGroups()
i++
continue
}
}
} else {
attributemap.set(attribute, [attribute.range[1], false])
addtoSortableAttributeGroups()
}
}
}
return sortableAttributeGroups;
Expand All @@ -155,6 +216,7 @@ const generateFixerFunction = (node, context, reservedList) => {
const noSortAlphabetically = configuration.noSortAlphabetically || false;
const reservedFirst = configuration.reservedFirst || false;
const locale = configuration.locale || 'auto';
const commentbetween = configuration.commentbetween || true;

// Sort props according to the context. Only supports ignoreCase.
// Since we cannot safely move JSXSpreadAttribute (due to potential variable overrides),
Expand All @@ -169,23 +231,24 @@ const generateFixerFunction = (node, context, reservedList) => {
reservedFirst,
reservedList,
locale,
commentbetween,
};
const sortableAttributeGroups = getGroupsOfSortableAttributes(attributes);
const sortableAttributeGroups = getGroupsOfSortableAttributes(attributes, context);
const sortedAttributeGroups = sortableAttributeGroups
.slice(0)
.map((group) => group.slice(0).sort((a, b) => contextCompare(a, b, options)));
.map((group) => group.slice(0).sort((a, b) => contextCompare(a, b, options) ));

return function fixFunction(fixer) {
const fixers = [];
let source = sourceCode.getText();

// Replace each unsorted attribute with the sorted one.
sortableAttributeGroups.forEach((sortableGroup, ii) => {
sortableGroup.forEach((attr, jj) => {
const sortedAttr = sortedAttributeGroups[ii][jj];
const sortedAttrText = sourceCode.getText(sortedAttr);
const sortedAttrText = source.substring(sortedAttr.range[0], attributemap.get(sortedAttr)[0])
const attrrangeEnd = attributemap.get(attr)[0]
fixers.push({
range: [attr.range[0], attr.range[1]],
range: [attr.range[0], attrrangeEnd],
text: sortedAttrText,
});
});
Expand All @@ -194,7 +257,7 @@ const generateFixerFunction = (node, context, reservedList) => {
fixers.sort((a, b) => b.range[0] - a.range[0]);

const rangeStart = fixers[fixers.length - 1].range[0];
const rangeEnd = fixers[0].range[1];
const rangeEnd = fixers[0].range[1];

fixers.forEach((fix) => {
source = `${source.substr(0, fix.range[0])}${fix.text}${source.substr(fix.range[1])}`;
Expand Down Expand Up @@ -262,10 +325,11 @@ function reportNodeAttribute(nodeAttribute, errorType, node, context, reservedLi
errors.push(errorType);

reportedNodeAttributes.set(nodeAttribute, errors);

report(context, messages[errorType], errorType, {
node: nodeAttribute.name,
fix: generateFixerFunction(node, context, reservedList),

});
}

Expand Down

0 comments on commit 51ed373

Please sign in to comment.