Skip to content

Commit 3d63c38

Browse files
authored
fix: display raw key in the message (#179)
* fix: display raw key in the message * wip * wip * wip * wip * wip * wip * wip
1 parent fa737ea commit 3d63c38

File tree

8 files changed

+238
-34
lines changed

8 files changed

+238
-34
lines changed

src/rules/no-duplicate-keys.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
* @author Nicholas C. Zakas
44
*/
55

6+
//-----------------------------------------------------------------------------
7+
// Imports
8+
//-----------------------------------------------------------------------------
9+
10+
import { getKey, getRawKey } from "../util.js";
11+
612
//-----------------------------------------------------------------------------
713
// Type Definitions
814
//-----------------------------------------------------------------------------
@@ -49,23 +55,22 @@ const rule = {
4955
},
5056

5157
Member(node) {
52-
const key =
53-
node.name.type === "String"
54-
? node.name.value
55-
: node.name.name;
58+
const key = getKey(node);
59+
const rawKey = getRawKey(node, context.sourceCode);
5660

5761
if (keys.has(key)) {
5862
context.report({
5963
loc: node.name.loc,
6064
messageId: "duplicateKey",
6165
data: {
62-
key,
66+
key: rawKey,
6367
},
6468
});
6569
} else {
6670
keys.set(key, node);
6771
}
6872
},
73+
6974
"Object:exit"() {
7075
keys = objectKeys.pop();
7176
},

src/rules/no-empty-keys.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
* @author Nicholas C. Zakas
44
*/
55

6+
//-----------------------------------------------------------------------------
7+
// Imports
8+
//-----------------------------------------------------------------------------
9+
10+
import { getKey } from "../util.js";
11+
612
//-----------------------------------------------------------------------------
713
// Type Definitions
814
//-----------------------------------------------------------------------------
@@ -37,10 +43,7 @@ const rule = {
3743
create(context) {
3844
return {
3945
Member(node) {
40-
const key =
41-
node.name.type === "String"
42-
? node.name.value
43-
: node.name.name;
46+
const key = getKey(node);
4447

4548
if (key.trim() === "") {
4649
context.report({

src/rules/no-unnormalized-keys.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
* @author Bradley Meck Farias
44
*/
55

6+
//-----------------------------------------------------------------------------
7+
// Imports
8+
//-----------------------------------------------------------------------------
9+
10+
import { getKey } from "../util.js";
11+
612
//-----------------------------------------------------------------------------
713
// Type Definitions
814
//-----------------------------------------------------------------------------
@@ -58,10 +64,7 @@ const rule = {
5864

5965
return {
6066
Member(node) {
61-
const key =
62-
node.name.type === "String"
63-
? node.name.value
64-
: node.name.name;
67+
const key = getKey(node);
6568

6669
if (key.normalize(form) !== key) {
6770
context.report({

src/rules/sort-keys.js

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//-----------------------------------------------------------------------------
1010

1111
import naturalCompare from "natural-compare";
12+
import { getKey, getRawKey } from "../util.js";
1213

1314
//-----------------------------------------------------------------------------
1415
// Type Definitions
@@ -76,17 +77,6 @@ const comparators = {
7677
},
7778
};
7879

79-
/**
80-
* Gets the MemberNode's string key value.
81-
* @param {MemberNode} member
82-
* @return {string}
83-
*/
84-
function getKey(member) {
85-
return member.name.type === "Identifier"
86-
? member.name.name
87-
: member.name.value;
88-
}
89-
9080
//-----------------------------------------------------------------------------
9181
// Rule Definition
9282
//-----------------------------------------------------------------------------
@@ -144,6 +134,7 @@ const rule = {
144134
},
145135

146136
create(context) {
137+
const { sourceCode } = context;
147138
const [
148139
directionShort,
149140
{ allowLineSeparatedGroups, caseSensitive, natural, minKeys },
@@ -156,7 +147,7 @@ const rule = {
156147

157148
// 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
158149
const commentLineNums = new Set();
159-
for (const comment of context.sourceCode.comments) {
150+
for (const comment of sourceCode.comments) {
160151
for (
161152
let lineNum = comment.loc.start.line;
162153
lineNum <= comment.loc.end.line;
@@ -187,9 +178,7 @@ const rule = {
187178
) {
188179
if (
189180
!commentLineNums.has(lineNum) &&
190-
!hasNonWhitespace.test(
191-
context.sourceCode.lines[lineNum - 1],
192-
)
181+
!hasNonWhitespace.test(sourceCode.lines[lineNum - 1])
193182
) {
194183
return true;
195184
}
@@ -200,15 +189,20 @@ const rule = {
200189

201190
return {
202191
Object(node) {
192+
/** @type {MemberNode} */
203193
let prevMember;
194+
/** @type {string} */
204195
let prevName;
196+
/** @type {string} */
197+
let prevRawName;
205198

206199
if (node.members.length < minKeys) {
207200
return;
208201
}
209202

210203
for (const member of node.members) {
211204
const thisName = getKey(member);
205+
const thisRawName = getRawKey(member, sourceCode);
212206

213207
if (
214208
prevMember &&
@@ -220,8 +214,8 @@ const rule = {
220214
loc: member.name.loc,
221215
messageId: "sortKeys",
222216
data: {
223-
thisName,
224-
prevName,
217+
thisName: thisRawName,
218+
prevName: prevRawName,
225219
direction,
226220
sensitivity,
227221
sortName,
@@ -231,6 +225,7 @@ const rule = {
231225

232226
prevMember = member;
233227
prevName = thisName;
228+
prevRawName = thisRawName;
234229
}
235230
},
236231
};

src/util.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* @fileoverview Utility Library
3+
* @author 루밀LuMir(lumirlumir)
4+
*/
5+
6+
//-----------------------------------------------------------------------------
7+
// Type Definitions
8+
//-----------------------------------------------------------------------------
9+
10+
/**
11+
* @import { MemberNode } from "@humanwhocodes/momoa";
12+
* @import { JSONSourceCode } from "./languages/json-source-code.js";
13+
*/
14+
15+
//-----------------------------------------------------------------------------
16+
// Helpers
17+
//-----------------------------------------------------------------------------
18+
19+
/**
20+
* Gets the `MemberNode`'s key value.
21+
* @param {MemberNode} node The node to get the key from.
22+
* @returns {string} The key value.
23+
*/
24+
export function getKey(node) {
25+
return node.name.type === "String" ? node.name.value : node.name.name;
26+
}
27+
28+
/**
29+
* Gets the `MemberNode`'s raw key value.
30+
* @param {MemberNode} node The node to get the raw key from.
31+
* @param {JSONSourceCode} sourceCode The JSON source code object.
32+
* @returns {string} The raw key value.
33+
*/
34+
export function getRawKey(node, sourceCode) {
35+
return node.name.type === "String"
36+
? sourceCode.getText(node.name, -1, -1)
37+
: sourceCode.getText(node.name);
38+
}

tests/rules/no-duplicate-keys.test.js

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,67 @@ ruleTester.run("no-duplicate-keys", rule, {
151151
},
152152
],
153153
},
154+
{
155+
code: '{"foot": 1, "fo\\u006ft": 2}',
156+
errors: [
157+
{
158+
messageId: "duplicateKey",
159+
data: { key: "fo\\u006ft" },
160+
line: 1,
161+
column: 13,
162+
endLine: 1,
163+
endColumn: 24,
164+
},
165+
],
166+
},
167+
{
168+
code: '{"foot": 1, "fo\\u006ft": 2}',
169+
language: "json/jsonc",
170+
errors: [
171+
{
172+
messageId: "duplicateKey",
173+
data: { key: "fo\\u006ft" },
174+
line: 1,
175+
column: 13,
176+
endLine: 1,
177+
endColumn: 24,
178+
},
179+
],
180+
},
181+
{
182+
code: '{"foot": 1, "fo\\u006ft": 2}',
183+
language: "json/json5",
184+
errors: [
185+
{
186+
messageId: "duplicateKey",
187+
data: { key: "fo\\u006ft" },
188+
line: 1,
189+
column: 13,
190+
endLine: 1,
191+
endColumn: 24,
192+
},
193+
],
194+
},
195+
{
196+
code: "{foot: 1, fo\\u006ft: 2}",
197+
language: "json/json5",
198+
errors: [
199+
{
200+
messageId: "duplicateKey",
201+
data: { key: "fo\\u006ft" },
202+
line: 1,
203+
column: 11,
204+
endLine: 1,
205+
endColumn: 20,
206+
},
207+
],
208+
},
154209
{
155210
code: '{"f\\u006fot": 1, "fo\\u006ft": 2}',
156211
errors: [
157212
{
158213
messageId: "duplicateKey",
159-
data: { key: "foot" },
214+
data: { key: "fo\\u006ft" },
160215
line: 1,
161216
column: 18,
162217
endLine: 1,
@@ -170,7 +225,7 @@ ruleTester.run("no-duplicate-keys", rule, {
170225
errors: [
171226
{
172227
messageId: "duplicateKey",
173-
data: { key: "foot" },
228+
data: { key: "fo\\u006ft" },
174229
line: 1,
175230
column: 18,
176231
endLine: 1,
@@ -184,7 +239,7 @@ ruleTester.run("no-duplicate-keys", rule, {
184239
errors: [
185240
{
186241
messageId: "duplicateKey",
187-
data: { key: "foot" },
242+
data: { key: "fo\\u006ft" },
188243
line: 1,
189244
column: 18,
190245
endLine: 1,
@@ -198,7 +253,7 @@ ruleTester.run("no-duplicate-keys", rule, {
198253
errors: [
199254
{
200255
messageId: "duplicateKey",
201-
data: { key: "foot" },
256+
data: { key: "fo\\u006ft" },
202257
line: 1,
203258
column: 16,
204259
endLine: 1,

tests/rules/sort-keys.test.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2401,5 +2401,45 @@ ruleTester.run("sort-keys", rule, {
24012401
},
24022402
],
24032403
},
2404+
2405+
// Escape sequences in keys
2406+
{
2407+
code: '{"\\u0061":1, "\\u0063":2, "\\u0062":3}',
2408+
errors: [
2409+
{
2410+
messageId: "sortKeys",
2411+
data: {
2412+
sortName: "alphanumeric",
2413+
sensitivity: "sensitive",
2414+
direction: "ascending",
2415+
thisName: "\\u0062",
2416+
prevName: "\\u0063",
2417+
},
2418+
line: 1,
2419+
column: 26,
2420+
endLine: 1,
2421+
endColumn: 34,
2422+
},
2423+
],
2424+
},
2425+
{
2426+
code: '{"\\u0061\\n":1, "\\u0063\\n":2, "\\u0062\\n":3}',
2427+
errors: [
2428+
{
2429+
messageId: "sortKeys",
2430+
data: {
2431+
sortName: "alphanumeric",
2432+
sensitivity: "sensitive",
2433+
direction: "ascending",
2434+
thisName: "\\u0062\\n",
2435+
prevName: "\\u0063\\n",
2436+
},
2437+
line: 1,
2438+
column: 30,
2439+
endLine: 1,
2440+
endColumn: 40,
2441+
},
2442+
],
2443+
},
24042444
],
24052445
});

0 commit comments

Comments
 (0)