Skip to content

Commit 4e8029c

Browse files
committed
Fix invalid JSON escapes errors
1 parent 02d6bc0 commit 4e8029c

File tree

4 files changed

+27
-5
lines changed

4 files changed

+27
-5
lines changed

src/DiagnosticCollection.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as vscodeOniguruma from 'vscode-oniguruma';
44
import * as textmateOnigmo from "./Onigmo/Onigmo";
55
import * as PCRE from '@syntropiq/libpcre-ts';
66
import * as onigurumaToES from 'oniguruma-to-es';
7-
import { closeEnoughQuestionMark, DocumentSelector, getPackageJSON, stringify, wagnerFischer } from "./extension";
7+
import { closeEnoughQuestionMark, DocumentSelector, getPackageJSON, JSONParseStringRelaxed, stringify, wagnerFischer } from "./extension";
88
import { getLastNode, getTrees, queryNode, toRange, trees } from "./TreeSitter";
99
import { ignoreDiagnosticsUnusedRepos } from "./Providers/CodeActionsProvider";
1010
import { unicodeproperties } from "./UNICODE_PROPERTIES";
@@ -407,7 +407,7 @@ async function diagnosticsOnigurumaRegexErrors(diagnostics: vscode.Diagnostic[],
407407

408408
let groupCaptures!: webTreeSitter.QueryCapture[];
409409

410-
const regex: string = JSON.parse(`"${text}"`);
410+
const regex: string = JSONParseStringRelaxed(text);
411411
const hasBackreferences = (key.text == 'end' || key.text == 'while') && /\\[0-9]/.test(regex);
412412
const beginNode = hasBackreferences ? getLastNode(regexNode.parent!.parent!, 'begin')?.childForFieldName('regex') : null;
413413
if (beginNode) {

src/Providers/CodeActionsProvider.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as vscode from 'vscode';
22
import * as webTreeSitter from 'web-tree-sitter';
33
import * as optimizer from 'oniguruma-parser-cjs/optimizer';
4-
import { closeEnoughQuestionMark, stringify, wagnerFischer } from "../extension";
4+
import { closeEnoughQuestionMark, JSONParseStringRelaxed, stringify, wagnerFischer } from "../extension";
55
import { getTrees, queryNode, toRange } from "../TreeSitter";
66
import { debouncedDiagnostics } from "../DiagnosticCollection";
77
import { unicodeproperties, UNICODE_PROPERTIES } from "../UNICODE_PROPERTIES";
@@ -223,7 +223,7 @@ async function optimizeRegex(edit: vscode.WorkspaceEdit, regexNode: webTreeSitte
223223
const range = toRange(regexNode);
224224

225225
try {
226-
const text: string = JSON.parse(`"${regexNode.text}"`);
226+
const text: string = JSONParseStringRelaxed(regexNode.text);
227227

228228
const optimized = optimizer.optimize(text, {
229229
rules: {

src/Providers/HoverProvider.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as vscode from 'vscode';
22
import * as webTreeSitter from 'web-tree-sitter';
33
import * as onigurumaToES from 'oniguruma-to-es';
4+
import { JSONParseStringRelaxed } from "../extension";
45
import { getTrees, queryNode, toPoint, toRange, trees } from "../TreeSitter";
56

67

@@ -70,7 +71,7 @@ export const HoverProvider: vscode.HoverProvider = {
7071
try {
7172
const regexNode = hoverNode.parent?.childForFieldName('regex');
7273
if (regexNode?.text) {
73-
const text: string = JSON.parse(`"${regexNode.text}"`);
74+
const text: string = JSONParseStringRelaxed(regexNode.text);
7475
const options: onigurumaToES.ToRegExpOptions = {
7576
accuracy: 'default',
7677
avoidSubclass: true,

src/extension.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,27 @@ export function stringify(this: any, key: string, value: any): any {
109109
return value;
110110
}
111111

112+
export function JSONParseStringRelaxed(string: string) {
113+
return string.replaceAll(
114+
/\\u[0-9A-Fa-f]{1,4}|\\.?/g,
115+
(escapeString) => {
116+
const escapeChar = escapeString.charAt(1);
117+
switch (escapeChar) {
118+
case 'u': // unicode \u0000
119+
const hexadecimalString = escapeString.substring(2, 6);
120+
const hexadecimalCode = parseInt(hexadecimalString, 16);
121+
return String.fromCodePoint(hexadecimalCode);
122+
case 'b': return '\b'; // backspace
123+
case 'f': return '\f'; // form feed
124+
case 'n': return '\n'; // newline
125+
case 'r': return '\r'; // carriage return
126+
case 't': return '\t'; // tab
127+
default:
128+
return escapeChar;
129+
}
130+
}
131+
);
132+
}
112133

113134
export function closeEnoughQuestionMark(distance: number, text: string): boolean {
114135
if (typeof distance != 'number') {

0 commit comments

Comments
 (0)