feat(hint): H2 Phase C batch 4 — advanced-mode SQL tier-3 hints (ADR-0053)
Distinct SQL-syntax hints for the 11 advanced-mode forms: sql create table / alter table / create index / drop index / drop table / insert / update / delete, select, with, explain. hint_ids wired on all 11 nodes. Hardened hint_key_for_input_in_mode for shared entry words: a bare multi-form entry word defers to tier-2; when the second token isn't a form word (insert into / update … set), it falls back to the mode-primary key — so advanced mode resolves to the SQL form and simple mode to the DSL form. catalogue + keys.rs registered. +2 spot tests + grammar mode-disambiguation asserts; 2495 pass / 1 ignored, clippy clean.
This commit is contained in:
+38
-1
@@ -616,10 +616,13 @@ pub fn usage_keys_for_input_in_mode(
|
||||
/// form has no tier-3 block yet (the caller falls back to tier-2).
|
||||
#[must_use]
|
||||
pub fn hint_key_for_input_in_mode(source: &str, mode: crate::mode::Mode) -> Option<&'static str> {
|
||||
use crate::dsl::walker::lex_helpers::{consume_ident, skip_whitespace};
|
||||
let nodes = selected_nodes_for_input_in_mode(source, mode);
|
||||
if nodes.is_empty() {
|
||||
return None;
|
||||
}
|
||||
// Mode-ordered union (advanced-primary first in advanced mode), so a
|
||||
// shared entry word resolves to the surface the user is in.
|
||||
let mut keys: Vec<&'static str> = Vec::new();
|
||||
for (_, node, _) in &nodes {
|
||||
for k in node.hint_ids {
|
||||
@@ -628,7 +631,25 @@ pub fn hint_key_for_input_in_mode(source: &str, mode: crate::mode::Mode) -> Opti
|
||||
}
|
||||
}
|
||||
}
|
||||
pick_form_key(source, &keys)
|
||||
if keys.is_empty() {
|
||||
return None;
|
||||
}
|
||||
if keys.len() == 1 {
|
||||
return Some(keys[0]);
|
||||
}
|
||||
// A bare multi-form entry word (no form word yet — `add`⏎) has no
|
||||
// chosen form: defer to tier-2, which lists the choices.
|
||||
let start = skip_whitespace(source, 0);
|
||||
if let Some((_, entry_end)) = consume_ident(source, start)
|
||||
&& skip_whitespace(source, entry_end) >= source.len()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
// A form word picks the form (`drop column` → `drop_column`); when
|
||||
// the second token isn't a form word (`insert into …`, `update …
|
||||
// set`), fall back to the mode-primary key — in advanced mode the
|
||||
// SQL form, in simple mode the DSL form.
|
||||
pick_form_key(source, &keys).or_else(|| keys.first().copied())
|
||||
}
|
||||
|
||||
/// Shared mode-aware command-form selection for the entry word at the
|
||||
@@ -922,6 +943,22 @@ mod hint_key_tests {
|
||||
hint_key_for_input_in_mode("drop table T", Mode::Simple),
|
||||
Some("drop_table")
|
||||
);
|
||||
// Mode picks the surface for a shared entry word whose second
|
||||
// token isn't a form word: SQL form in advanced, DSL in simple.
|
||||
assert_eq!(
|
||||
hint_key_for_input_in_mode("insert into T values (1)", Mode::Advanced),
|
||||
Some("sql_insert")
|
||||
);
|
||||
assert_eq!(
|
||||
hint_key_for_input_in_mode("insert into T values (1)", Mode::Simple),
|
||||
Some("insert")
|
||||
);
|
||||
// `create table` shares a form word — advanced-first ordering
|
||||
// resolves it to the SQL form in advanced mode.
|
||||
assert_eq!(
|
||||
hint_key_for_input_in_mode("create table T (id int)", Mode::Advanced),
|
||||
Some("sql_create_table")
|
||||
);
|
||||
// Unknown entry word → None (tier-2 fallback).
|
||||
assert_eq!(hint_key_for_input_in_mode("zzz", Mode::Simple), None);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user