fix(editor): support Unicode SQL completion prefixes
This commit is contained in:
3 files changed
+91
-11
No files matched your search
@@ -183,7 +183,12 @@ export function sqlCompletionContextFromSemantic(model: SqlSemanticModel, base:
|
||||
}
|
||||
|
||||
const scope = sqlSemanticCompletionScope(model);
|
||||
const qualifier = model.cursorIntent.qualifierParts.length > 0 ? model.cursorIntent.qualifierParts.join(".") : undefined;
|
||||
const contextKind = semanticContextKind(model);
|
||||
const basePrefixHasNonAscii = Array.from(base.prefix).some((character) => (character.codePointAt(0) ?? 0) > 0x7f);
|
||||
const useBaseTrailingIdentifier = basePrefixHasNonAscii && model.cursorIntent.prefix.length === 0 && model.cursorIntent.replacementRange.start === model.cursorIntent.replacementRange.end && base.contextKind === contextKind;
|
||||
const prefix = useBaseTrailingIdentifier ? base.prefix : model.cursorIntent.prefix;
|
||||
const qualifierParts = model.cursorIntent.qualifierParts.length > 0 ? [...model.cursorIntent.qualifierParts] : useBaseTrailingIdentifier ? base.qualifierParts : undefined;
|
||||
const qualifier = qualifierParts?.join(".");
|
||||
const referencedTables = sqlSemanticReferencedTables(model);
|
||||
const mutationTarget = semanticMutationTarget(model);
|
||||
const mutationDatabase = mutationTarget?.metadataTarget?.database;
|
||||
@@ -195,9 +200,9 @@ export function sqlCompletionContextFromSemantic(model: SqlSemanticModel, base:
|
||||
|
||||
return {
|
||||
...base,
|
||||
prefix: model.cursorIntent.prefix,
|
||||
prefix,
|
||||
qualifier,
|
||||
qualifierParts: model.cursorIntent.qualifierParts.length > 0 ? [...model.cursorIntent.qualifierParts] : undefined,
|
||||
qualifierParts,
|
||||
suggestTables,
|
||||
suggestColumns,
|
||||
suggestKeywords: scope.kind === "keyword" || (!suggestTables && !suggestColumns && !suggestRoutines),
|
||||
@@ -215,6 +220,6 @@ export function sqlCompletionContextFromSemantic(model: SqlSemanticModel, base:
|
||||
updateTarget: model.cursorIntent.kind === "update_column" && mutationTarget ? { table: mutationTarget.name, schema: mutationSchema } : base.updateTarget,
|
||||
deleteTarget: model.cursorIntent.kind === "delete_target" && mutationTarget ? { table: mutationTarget.name, schema: mutationSchema } : base.deleteTarget,
|
||||
onStar: model.cursorIntent.kind === "star" || base.onStar,
|
||||
contextKind: semanticContextKind(model),
|
||||
contextKind,
|
||||
};
|
||||
}
|
||||
@@ -1721,6 +1721,8 @@ function isCallRoutineContext(beforeToken: string): boolean {
|
||||
return /\bcall\s+(?:[A-Za-z_][\w$]*\.)?$/i.test(beforeToken) || /\bcall\s+(?:[A-Za-z_][\w$]*\.)?[A-Za-z_][\w$]*$/i.test(beforeToken);
|
||||
}
|
||||
|
||||
const SQL_IDENTIFIER_START_CHAR = /[@_\p{ID_Start}]/u;
|
||||
const SQL_IDENTIFIER_SUFFIX = /[$@_\u200c\u200d\p{ID_Continue}]+$/u;
|
||||
const SQL_IDENTIFIER_CONTINUE_CHAR = /[$_\u200c\u200d\p{ID_Continue}]/u;
|
||||
|
||||
function hasTableAliasAfterCursor(sql: string, cursor: number): boolean {
|
||||
@@ -2022,13 +2024,12 @@ function parseTrailingIdentifierPart(input: string, endExclusive: number): { sta
|
||||
return null;
|
||||
}
|
||||
|
||||
let start = end;
|
||||
while (start >= 0 && /[A-Za-z0-9_$@]/.test(input[start] ?? "")) start -= 1;
|
||||
start += 1;
|
||||
if (start >= endExclusive) return null;
|
||||
const raw = input.slice(start, endExclusive);
|
||||
if (!/^[@A-Za-z_][\w$@]*$/.test(raw)) return null;
|
||||
return { start, raw };
|
||||
const match = SQL_IDENTIFIER_SUFFIX.exec(input.slice(0, endExclusive));
|
||||
if (!match) return null;
|
||||
const raw = match[0];
|
||||
const firstCodePoint = raw.codePointAt(0);
|
||||
if (firstCodePoint === undefined || !SQL_IDENTIFIER_START_CHAR.test(String.fromCodePoint(firstCodePoint))) return null;
|
||||
return { start: match.index, raw };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user