feat: H1a parse-error gaps G2–G4 + advanced near-miss matrix (ADR-0042)
Close the three remaining ADR-0042 triage gaps, each test-first, and lock the advanced-mode near-miss matrix. G2 — bare `select` dumped the 14-item expression first-set. Collapse it to "a projection: `*`, a column, or an expression" in the error message only (parser::format_walker_error), detected by the joint `distinct`+`all` quantifier signature unique to a projection start. Render-only: completion/hints still expand the full set (typing-surface matrix unchanged). G3 — the usage block was mode-blind: advanced `create table` showed the DSL `create table … with pk …` template. usage_key(s)_for_input gain mode-aware `_in_mode` variants selecting candidates by CommandCategory; render_usage_block and the typing-time ambient usage thread the submission mode. Advanced `create` now shows both SQL forms. A fallback covers shared SQL nodes (insert/update/delete) that declare no usage_ids of their own — without it they regressed to the available-commands fallback (caught by the new advanced matrix). G4 — `with` borrowed `select`'s usage template; give it its own parse.usage.with CTE template. Tests: new near_miss_matrix_advanced_mode (12 SQL-surface cases incl. the available-commands regression guard) + per-gap tests; removed the temporary baseline_dump. Full suite green (lib 1578 / it 386 / typing_surface_matrix 192); clippy clean.
This commit is contained in:
+8
-6
@@ -1521,7 +1521,7 @@ impl App {
|
||||
for note in notes {
|
||||
self.note_error(note);
|
||||
}
|
||||
self.note_error(render_usage_block(input));
|
||||
self.note_error(render_usage_block(input, mode));
|
||||
return vec![Action::JournalFailure {
|
||||
source: input.to_string(),
|
||||
}];
|
||||
@@ -1601,7 +1601,7 @@ impl App {
|
||||
// known command-entry keyword was consumed) or
|
||||
// the available-commands fallback (§5).
|
||||
if let ParseError::Invalid { .. } = &err {
|
||||
self.note_error(render_usage_block(input));
|
||||
self.note_error(render_usage_block(input, mode));
|
||||
}
|
||||
// ADR-0034 §1/§2: a submitted line that failed to
|
||||
// parse is journalled `err` so it is recallable
|
||||
@@ -2557,16 +2557,18 @@ fn parse_error_message(err: &ParseError) -> String {
|
||||
/// renders every catalog template — multi-form families like
|
||||
/// `drop` show every variant. Otherwise the fallback lists every
|
||||
/// entry keyword alphabetically.
|
||||
fn render_usage_block(input: &str) -> String {
|
||||
fn render_usage_block(input: &str, mode: Mode) -> String {
|
||||
// A multi-form command that has committed to a form
|
||||
// (`add index …`) shows only that form's usage; a bare
|
||||
// multi-form entry word (`add`) shows the whole family.
|
||||
// Mode-aware (ADR-0042 G3): in advanced mode a shared entry
|
||||
// word shows its SQL forms, not the DSL templates.
|
||||
let catalog_keys: Vec<&'static str> =
|
||||
crate::dsl::grammar::usage_key_for_input(input)
|
||||
crate::dsl::grammar::usage_key_for_input_in_mode(input, mode)
|
||||
.map(|key| vec![key])
|
||||
.or_else(|| {
|
||||
crate::dsl::grammar::usage_keys_for_input(input)
|
||||
.map(|(_word, all)| all.to_vec())
|
||||
crate::dsl::grammar::usage_keys_for_input_in_mode(input, mode)
|
||||
.map(|(_word, all)| all)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
if !catalog_keys.is_empty() {
|
||||
|
||||
Reference in New Issue
Block a user