Skip to content

Commit cb53731

Browse files
authored
Change to be independent of eslint-utils (#119)
1 parent 61c4211 commit cb53731

File tree

7 files changed

+270
-54
lines changed

7 files changed

+270
-54
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@
7575
},
7676
"dependencies": {
7777
"acorn": "^8.5.0",
78-
"eslint-utils": "^3.0.0",
7978
"eslint-visitor-keys": "^3.0.0",
8079
"espree": "^9.0.0",
8180
"semver": "^7.3.5"

src/parser/validate.ts

Lines changed: 22 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import type {
1111
BinaryExpression,
1212
Expression,
1313
} from "estree"
14-
import type * as eslintUtils from "eslint-utils"
1514
import {
1615
throwUnexpectedNodeError,
1716
throwExpectedTokenError,
@@ -24,56 +23,35 @@ import type { TokenStore, MaybeNodeOrToken } from "./token-store"
2423
import { isComma } from "./token-store"
2524
import { isRegExpLiteral } from "./utils"
2625
import type { JSONIdentifier } from "./ast"
27-
import {
28-
loadNewest,
29-
requireFromCwd,
30-
requireFromLinter,
31-
} from "./modules/require-utils"
3226
import type { JSONSyntaxContext } from "./syntax-context"
3327

3428
const lineBreakPattern = /\r\n|[\n\r\u2028\u2029]/u
3529
const octalNumericLiteralPattern = /^0[Oo]/u
3630
const legacyOctalNumericLiteralPattern = /^0\d/u
3731
const binaryNumericLiteralPattern = /^0[Bb]/u
3832

39-
let cacheCodePointEscapeMatcher: eslintUtils.PatternMatcher | null
33+
const unicodeCodepointEscapePattern = /\\u\{[\dA-Fa-f]+\}/uy
4034

41-
/** Get codePointEscape matcher */
42-
function getCodePointEscapeMatcher(): eslintUtils.PatternMatcher {
43-
if (!cacheCodePointEscapeMatcher) {
44-
const utils: typeof eslintUtils = loadNewest([
45-
{
46-
getPkg() {
47-
return requireFromCwd("eslint-utils/package.json")
48-
},
49-
get() {
50-
return requireFromCwd("eslint-utils")
51-
},
52-
},
53-
{
54-
getPkg() {
55-
return requireFromLinter("eslint-utils/package.json")
56-
},
57-
get() {
58-
return requireFromLinter("eslint-utils")
59-
},
60-
},
61-
{
62-
getPkg() {
63-
// eslint-disable-next-line @typescript-eslint/no-require-imports -- special require
64-
return require("eslint-utils/package.json")
65-
},
66-
get() {
67-
// eslint-disable-next-line @typescript-eslint/no-require-imports -- special require
68-
return require("eslint-utils")
69-
},
70-
},
71-
])
72-
cacheCodePointEscapeMatcher = new utils.PatternMatcher(
73-
/\\u\{[\dA-Fa-f]+\}/gu,
74-
)
35+
/**
36+
* Check if given string has unicode codepoint escape
37+
*/
38+
function hasUnicodeCodepointEscapes(code: string) {
39+
let escaped = false
40+
for (let index = 0; index < code.length - 4; index++) {
41+
if (escaped) {
42+
escaped = false
43+
continue
44+
}
45+
const char = code[index]
46+
if (char === "\\") {
47+
unicodeCodepointEscapePattern.lastIndex = index
48+
if (unicodeCodepointEscapePattern.test(code)) {
49+
return true
50+
}
51+
escaped = true
52+
}
7553
}
76-
return cacheCodePointEscapeMatcher
54+
return false
7755
}
7856

7957
/**
@@ -361,7 +339,7 @@ function validateLiteral(node: Literal, ctx: JSONSyntaxContext) {
361339
}
362340
}
363341
if (!ctx.unicodeCodepointEscapes) {
364-
if (getCodePointEscapeMatcher().test(node.raw!)) {
342+
if (hasUnicodeCodepointEscapes(node.raw!)) {
365343
throw throwUnexpectedError("unicode codepoint escape", node)
366344
}
367345
}
@@ -463,7 +441,7 @@ function validateTemplateLiteralNode(
463441
}
464442

465443
if (!ctx.unicodeCodepointEscapes) {
466-
if (getCodePointEscapeMatcher().test(node.quasis[0].value.raw)) {
444+
if (hasUnicodeCodepointEscapes(node.quasis[0].value.raw)) {
467445
throw throwUnexpectedError("unicode codepoint escape", node)
468446
}
469447
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"\\u{31}":"\\u{31}"}
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
{
2+
"type": "Program",
3+
"body": [
4+
{
5+
"type": "JSONExpressionStatement",
6+
"expression": {
7+
"type": "JSONObjectExpression",
8+
"properties": [
9+
{
10+
"type": "JSONProperty",
11+
"key": {
12+
"type": "JSONLiteral",
13+
"value": "\\u{31}",
14+
"raw": "\"\\\\u{31}\"",
15+
"range": [
16+
1,
17+
10
18+
],
19+
"loc": {
20+
"start": {
21+
"line": 1,
22+
"column": 1
23+
},
24+
"end": {
25+
"line": 1,
26+
"column": 10
27+
}
28+
}
29+
},
30+
"value": {
31+
"type": "JSONLiteral",
32+
"value": "\\u{31}",
33+
"raw": "\"\\\\u{31}\"",
34+
"range": [
35+
11,
36+
20
37+
],
38+
"loc": {
39+
"start": {
40+
"line": 1,
41+
"column": 11
42+
},
43+
"end": {
44+
"line": 1,
45+
"column": 20
46+
}
47+
}
48+
},
49+
"kind": "init",
50+
"computed": false,
51+
"method": false,
52+
"shorthand": false,
53+
"range": [
54+
1,
55+
20
56+
],
57+
"loc": {
58+
"start": {
59+
"line": 1,
60+
"column": 1
61+
},
62+
"end": {
63+
"line": 1,
64+
"column": 20
65+
}
66+
}
67+
}
68+
],
69+
"range": [
70+
0,
71+
21
72+
],
73+
"loc": {
74+
"start": {
75+
"line": 1,
76+
"column": 0
77+
},
78+
"end": {
79+
"line": 1,
80+
"column": 21
81+
}
82+
}
83+
},
84+
"range": [
85+
0,
86+
21
87+
],
88+
"loc": {
89+
"start": {
90+
"line": 1,
91+
"column": 0
92+
},
93+
"end": {
94+
"line": 1,
95+
"column": 21
96+
}
97+
}
98+
}
99+
],
100+
"comments": [],
101+
"tokens": [
102+
{
103+
"type": "Punctuator",
104+
"value": "{",
105+
"range": [
106+
0,
107+
1
108+
],
109+
"loc": {
110+
"start": {
111+
"line": 1,
112+
"column": 0
113+
},
114+
"end": {
115+
"line": 1,
116+
"column": 1
117+
}
118+
}
119+
},
120+
{
121+
"type": "String",
122+
"value": "\"\\\\u{31}\"",
123+
"range": [
124+
1,
125+
10
126+
],
127+
"loc": {
128+
"start": {
129+
"line": 1,
130+
"column": 1
131+
},
132+
"end": {
133+
"line": 1,
134+
"column": 10
135+
}
136+
}
137+
},
138+
{
139+
"type": "Punctuator",
140+
"value": ":",
141+
"range": [
142+
10,
143+
11
144+
],
145+
"loc": {
146+
"start": {
147+
"line": 1,
148+
"column": 10
149+
},
150+
"end": {
151+
"line": 1,
152+
"column": 11
153+
}
154+
}
155+
},
156+
{
157+
"type": "String",
158+
"value": "\"\\\\u{31}\"",
159+
"range": [
160+
11,
161+
20
162+
],
163+
"loc": {
164+
"start": {
165+
"line": 1,
166+
"column": 11
167+
},
168+
"end": {
169+
"line": 1,
170+
"column": 20
171+
}
172+
}
173+
},
174+
{
175+
"type": "Punctuator",
176+
"value": "}",
177+
"range": [
178+
20,
179+
21
180+
],
181+
"loc": {
182+
"start": {
183+
"line": 1,
184+
"column": 20
185+
},
186+
"end": {
187+
"line": 1,
188+
"column": 21
189+
}
190+
}
191+
}
192+
],
193+
"range": [
194+
0,
195+
21
196+
],
197+
"loc": {
198+
"start": {
199+
"line": 1,
200+
"column": 0
201+
},
202+
"end": {
203+
"line": 1,
204+
"column": 21
205+
}
206+
}
207+
}

tests/src/parser/parser.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,19 @@ import { nodeReplacer } from "./utils"
1010

1111
const FIXTURE_ROOT = path.resolve(__dirname, "../../fixtures/parser/ast")
1212

13-
function parse(code: string) {
14-
return parseJSON(code, { ecmaVersion: 2021 })
13+
function parse(code: string, fileName: string) {
14+
const ext = path.extname(fileName)
15+
return parseJSON(code, {
16+
ecmaVersion: 2021,
17+
jsonSyntax:
18+
ext === ".json"
19+
? "JSON"
20+
: ext === ".jsonc"
21+
? "JSONC"
22+
: ext === ".json5"
23+
? "JSON5"
24+
: undefined,
25+
})
1526
}
1627

1728
describe("Check for AST.", () => {
@@ -21,16 +32,18 @@ describe("Check for AST.", () => {
2132
(f) =>
2233
f.endsWith("input.json5") ||
2334
f.endsWith("input.json6") ||
24-
f.endsWith("input.jsonx"),
35+
f.endsWith("input.jsonx") ||
36+
f.endsWith("input.jsonc") ||
37+
f.endsWith("input.json"),
2538
)) {
2639
const inputFileName = path.join(FIXTURE_ROOT, filename)
2740
const outputFileName = inputFileName.replace(
28-
/input\.json[56x]$/u,
41+
/input\.json[56cx]?$/u,
2942
"output.json",
3043
)
3144

3245
const requirementsPath = inputFileName.replace(
33-
/input\.json[56x]$/u,
46+
/input\.json[56cx]?$/u,
3447
"requirements.json",
3548
)
3649
const requirements = fs.existsSync(requirementsPath)
@@ -49,7 +62,7 @@ describe("Check for AST.", () => {
4962
}
5063
it(`AST:${filename}`, () => {
5164
const input = fs.readFileSync(inputFileName, "utf8")
52-
const ast = parse(input)
65+
const ast = parse(input, inputFileName)
5366
const astJson = JSON.stringify(ast, nodeReplacer, 2)
5467
const output = fs.readFileSync(outputFileName, "utf8")
5568
assert.strictEqual(astJson, output)
@@ -58,7 +71,7 @@ describe("Check for AST.", () => {
5871
})
5972
it(`Static Value:${filename}`, () => {
6073
const input = fs.readFileSync(inputFileName, "utf8")
61-
const ast = parse(input)
74+
const ast = parse(input, inputFileName)
6275
const value = getStaticJSONValue(ast)
6376

6477
assert.deepStrictEqual(

0 commit comments

Comments
 (0)