Skip to content

Commit

Permalink
make sort-keys handle multiline comments
Browse files Browse the repository at this point in the history
  • Loading branch information
RobertAKARobin committed Jan 14, 2025
1 parent b5a6a23 commit 337dd83
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 33 deletions.
85 changes: 52 additions & 33 deletions src/rules/sort-keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ export default {
],
},

/**
* Note that the comma after a member is *not* included in `member.loc`, therefore the comma position is irrelevant
*/
create(context) {
const [
directionShort,
Expand All @@ -98,11 +101,38 @@ export default {
const sensitivity = caseSensitive ? "sensitive" : "insensitive";
const isValidOrder = comparators[direction][sortName][sensitivity];

const commentLines = new Set();
// Note that @humanwhocodes/momoa doesn't include comments in the object.members tree, so we can't just see if a member is preceded by a comment
const commentLineNums = new Set();
// TODO: Only invoke this if the language supports comments
for (const comment of context.sourceCode.comments) {
commentLines.add(
`${comment.loc.start.line}:${comment.loc.end.line}`,
);
for (
let lineNum = comment.loc.start.line;
lineNum <= comment.loc.end.line;
lineNum += 1
) {
commentLineNums.add(lineNum);
}
}

// Note that there can be comments *inside* members, e.g. `{"foo: /* comment *\/ "bar"}`, but these are ignored when calculating line-separated groups
function isLineSeparated(prevMember, member) {
const prevLine = prevMember.loc.end.line;
const thisLine = member.loc.start.line;

if (thisLine - prevLine < 2) {
return false;
}

let lineNum = prevLine + 1;
while (lineNum < thisLine) {
if (commentLineNums.has(lineNum) === false) {
return true;
}

lineNum += 1;
}

return false;
}

return {
Expand All @@ -117,35 +147,24 @@ export default {
for (const member of node.members) {
const thisName = getKey(member);

if (prevMember) {
const prevLine = prevMember.loc.end.line;
const thisLine = member.loc.start.line;

const membersAreAdjacent =
thisLine - prevLine < 2 ||
commentLines.has(`${prevLine}:${thisLine}`) ||
commentLines.has(`${prevLine + 1}:${thisLine}`) ||
commentLines.has(`${prevLine}:${thisLine - 1}`) ||
commentLines.has(`${prevLine + 1}:${thisLine - 1}`);

if (
(membersAreAdjacent ||
allowLineSeparatedGroups === false) &&
isValidOrder(prevName, thisName) === false
) {
context.report({
node,
loc: member.name.loc,
messageId: "sortKeys",
data: {
thisName,
prevName,
direction,
sensitivity,
sortName,
},
});
}
if (
prevMember &&
isValidOrder(prevName, thisName) === false &&
(allowLineSeparatedGroups === false ||
isLineSeparated(prevMember, member) === false)
) {
context.report({
node,
loc: member.name.loc,
messageId: "sortKeys",
data: {
thisName,
prevName,
direction,
sensitivity,
sortName,
},
});
}

prevMember = member;
Expand Down
49 changes: 49 additions & 0 deletions tests/rules/sort-keys.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1943,5 +1943,54 @@ ruleTester.run("sort-keys", rule, {
},
],
},
{
code: `
{
"b": /*foo */ 1,
// some multiline comment
// using line comment style
"a": 2 // "a" and "b" are not line separated
}
`,
language: "json/jsonc",
options: ["asc", { allowLineSeparatedGroups: true }],
errors: [
{
messageId: "sortKeys",
data: {
sortName: "alphanumeric",
sensitivity: "sensitive",
direction: "ascending",
thisName: "a",
prevName: "b",
},
},
],
},
{
code: `
{
"b": 1,
/* some multiline comment
using block comment style */
/* here's another for good measure */
"a": 2 // "a" and "b" are not line separated
}
`,
language: "json/jsonc",
options: ["asc", { allowLineSeparatedGroups: true }],
errors: [
{
messageId: "sortKeys",
data: {
sortName: "alphanumeric",
sensitivity: "sensitive",
direction: "ascending",
thisName: "a",
prevName: "b",
},
},
],
},
],
});

0 comments on commit 337dd83

Please sign in to comment.