Skip to content

Commit 337dd83

Browse files
make sort-keys handle multiline comments
1 parent b5a6a23 commit 337dd83

File tree

2 files changed

+101
-33
lines changed

2 files changed

+101
-33
lines changed

src/rules/sort-keys.js

+52-33
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ export default {
8787
],
8888
},
8989

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

101-
const commentLines = new Set();
104+
// 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
105+
const commentLineNums = new Set();
106+
// TODO: Only invoke this if the language supports comments
102107
for (const comment of context.sourceCode.comments) {
103-
commentLines.add(
104-
`${comment.loc.start.line}:${comment.loc.end.line}`,
105-
);
108+
for (
109+
let lineNum = comment.loc.start.line;
110+
lineNum <= comment.loc.end.line;
111+
lineNum += 1
112+
) {
113+
commentLineNums.add(lineNum);
114+
}
115+
}
116+
117+
// Note that there can be comments *inside* members, e.g. `{"foo: /* comment *\/ "bar"}`, but these are ignored when calculating line-separated groups
118+
function isLineSeparated(prevMember, member) {
119+
const prevLine = prevMember.loc.end.line;
120+
const thisLine = member.loc.start.line;
121+
122+
if (thisLine - prevLine < 2) {
123+
return false;
124+
}
125+
126+
let lineNum = prevLine + 1;
127+
while (lineNum < thisLine) {
128+
if (commentLineNums.has(lineNum) === false) {
129+
return true;
130+
}
131+
132+
lineNum += 1;
133+
}
134+
135+
return false;
106136
}
107137

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

120-
if (prevMember) {
121-
const prevLine = prevMember.loc.end.line;
122-
const thisLine = member.loc.start.line;
123-
124-
const membersAreAdjacent =
125-
thisLine - prevLine < 2 ||
126-
commentLines.has(`${prevLine}:${thisLine}`) ||
127-
commentLines.has(`${prevLine + 1}:${thisLine}`) ||
128-
commentLines.has(`${prevLine}:${thisLine - 1}`) ||
129-
commentLines.has(`${prevLine + 1}:${thisLine - 1}`);
130-
131-
if (
132-
(membersAreAdjacent ||
133-
allowLineSeparatedGroups === false) &&
134-
isValidOrder(prevName, thisName) === false
135-
) {
136-
context.report({
137-
node,
138-
loc: member.name.loc,
139-
messageId: "sortKeys",
140-
data: {
141-
thisName,
142-
prevName,
143-
direction,
144-
sensitivity,
145-
sortName,
146-
},
147-
});
148-
}
150+
if (
151+
prevMember &&
152+
isValidOrder(prevName, thisName) === false &&
153+
(allowLineSeparatedGroups === false ||
154+
isLineSeparated(prevMember, member) === false)
155+
) {
156+
context.report({
157+
node,
158+
loc: member.name.loc,
159+
messageId: "sortKeys",
160+
data: {
161+
thisName,
162+
prevName,
163+
direction,
164+
sensitivity,
165+
sortName,
166+
},
167+
});
149168
}
150169

151170
prevMember = member;

tests/rules/sort-keys.test.js

+49
Original file line numberDiff line numberDiff line change
@@ -1943,5 +1943,54 @@ ruleTester.run("sort-keys", rule, {
19431943
},
19441944
],
19451945
},
1946+
{
1947+
code: `
1948+
{
1949+
"b": /*foo */ 1,
1950+
// some multiline comment
1951+
// using line comment style
1952+
"a": 2 // "a" and "b" are not line separated
1953+
}
1954+
`,
1955+
language: "json/jsonc",
1956+
options: ["asc", { allowLineSeparatedGroups: true }],
1957+
errors: [
1958+
{
1959+
messageId: "sortKeys",
1960+
data: {
1961+
sortName: "alphanumeric",
1962+
sensitivity: "sensitive",
1963+
direction: "ascending",
1964+
thisName: "a",
1965+
prevName: "b",
1966+
},
1967+
},
1968+
],
1969+
},
1970+
{
1971+
code: `
1972+
{
1973+
"b": 1,
1974+
/* some multiline comment
1975+
using block comment style */
1976+
/* here's another for good measure */
1977+
"a": 2 // "a" and "b" are not line separated
1978+
}
1979+
`,
1980+
language: "json/jsonc",
1981+
options: ["asc", { allowLineSeparatedGroups: true }],
1982+
errors: [
1983+
{
1984+
messageId: "sortKeys",
1985+
data: {
1986+
sortName: "alphanumeric",
1987+
sensitivity: "sensitive",
1988+
direction: "ascending",
1989+
thisName: "a",
1990+
prevName: "b",
1991+
},
1992+
},
1993+
],
1994+
},
19461995
],
19471996
});

0 commit comments

Comments
 (0)