fix(editor): include fullwidth parens in completion depth

This commit is contained in:
Mo-Moore
2026-09-23 16:30:07 +08:00
committed by GitHub
parent 391af14c75
commit 37a5413641
3 changed files with 49 additions and 9 deletions
+5 -4
View File
@@ -486,13 +486,14 @@ function stepLexState(sql: string, index: number, state: LexState, dialectId: st
}
return index + 1;
}
if (ch === "(") {
// Match tokenizeSqlSemantic: fullwidth () update nesting the same as ASCII ().
if (ch === "(" || ch === "\uFF08") {
state.depth += 1;
return index + 1;
return index + ch.length;
}
if (ch === ")") {
if (ch === ")" || ch === "\uFF09") {
state.depth = Math.max(0, state.depth - 1);
return index + 1;
return index + ch.length;
}
return index + 1;
}
+8 -5
View File
@@ -232,11 +232,14 @@ export function tokenizeSqlSemantic(input: string, dialectId = "mysql", options?
continue;
}
if ("(),.;*".includes(ch)) {
if (ch === ")") depth = Math.max(0, depth - 1);
tokens.push(token("punctuation", ch, start, start + 1, depth));
if (ch === "(") depth += 1;
index += 1;
// Fullwidth () (U+FF08/U+FF09) are common IME typos in Chinese locales; treat them like
// ASCII () for nesting depth so commas inside to_date(…, …) stay nested and do not split
// INSERT ... SELECT projections (insert value column hints).
if ("(),.;*".includes(ch) || ch === "\uFF08" || ch === "\uFF09") {
if (ch === ")" || ch === "\uFF09") depth = Math.max(0, depth - 1);
tokens.push(token("punctuation", ch, start, start + ch.length, depth));
if (ch === "(" || ch === "\uFF08") depth += 1;
index += ch.length;
continue;
}
+36
View File
@@ -279,6 +279,42 @@ test("keeps the hint for a projection whose alias names a different column", ()
);
});
test("does not split nested to_date arguments into extra SELECT projections", () => {
// ASCII parentheses: commas inside to_date(to_char(...), 'fmt') stay nested.
const ascii = [
"INSERT INTO t_demo (occur_date, company_no, company_name, dep_id, market_code)",
"SELECT",
" to_date(to_char(a.l_date), 'YYYYMMDD') as occur_date,",
" '01694' as company_no,",
" 'Acme Corp' as company_name,",
" d.dept_code as dep_id,",
" a.market_code",
"FROM dual a, dual d",
].join("\n");
assert.deepEqual(
parseInsertValueHints(ascii).map((hint) => ({ column: hint.column, text: ascii.slice(hint.from).split(/[\s,]/u, 1)[0] })),
[{ column: "market_code", text: "a.market_code" }],
);
// Fullwidth outer parentheses (common IME typo) must not treat the format-string comma as a
// top-level projection separator — that shifted every later hint by one.
const fullwidth = [
"INSERT INTO t_demo (occur_date, company_no, company_name, dep_id, market_code)",
"SELECT",
" to_date\uFF08to_char(a.l_date), 'YYYYMMDD'\uFF09 as occur_date,",
" '01694' as company_no,",
" 'Acme Corp' as company_name,",
" d.dept_code as dep_id,",
" a.market_code",
"FROM dual a, dual d",
].join("\n");
assert.equal(parseInsertValuesClauses(fullwidth)[0]?.rows[0]?.length, 5);
assert.deepEqual(
parseInsertValueHints(fullwidth).map((hint) => ({ column: hint.column, text: fullwidth.slice(hint.from).split(/[\s,]/u, 1)[0] })),
[{ column: "market_code", text: "a.market_code" }],
);
});
test("caps INSERT ... SELECT hints to the smaller target or projection count", () => {
assert.deepEqual(
parseInsertValueHints("INSERT INTO t (a, b) SELECT x, y, z FROM source").map((hint) => hint.column),