2g: advanced-mode highlight + engine.* wiring + matrix tests

Cross-cut verification matrix for ADR-0032 Phase 2 is now fully
populated with concrete test references — every row green. Filling
the matrix surfaced three real gaps that this commit closes.

1. Advanced-mode syntax highlighting (ADR-0030 §8 matrix row).
   The `ui.rs` Advanced branch routed through `plain_input_spans`,
   bypassing the highlight walker entirely. In production SQL
   keywords past the entry word rendered as plain identifiers.
   Fix: mode-aware variants of `highlight_runs`,
   `render_input_runs`, `lex_to_runs`, and `input_diagnostics`;
   the Advanced render path now uses the highlighted form with
   `Mode::Advanced`. `plain_input_spans` removed (unused).

2. Engine.* key wiring (ADR-0032 §11.4 / §13 matrix rows + handoff
   §3.3 follow-up). The four Phase-2 engine.* catalog entries
   were authored in 2d but never reached: `translate_generic`
   discarded the engine message and returned a vague catalog
   entry. Fix: pattern-match the engine message text for the four
   Phase-2 categories (aggregate misuse, group-by required,
   compound arity mismatch fallback, scalar-subquery cardinality)
   inside `translate_generic`, routing each to its engine-neutral
   catalog entry.

3. Matrix-coverage tests. Thirteen new tests covering the rows
   that had no explicit coverage:
   - 3 SQL keyword/operator/CASE highlight tests
   - 4 engine.* engine-message tests
   - 3 sql_expr column-completion tests (WHERE, HAVING)
   - 3 predicate-warning slot tests (CASE, ORDER BY, projection)
   - 1 all-10-playground-types recovery test (tests/sql_select.rs)

Plan document (docs/plans/20260520-adr-0032-phase-2.md) updated:
every (TBD) row in the cross-cut matrix replaced with a concrete
test file::function reference and a green status marker.

Test totals: 1428 → 1441 passing (+13 new). Clippy clean.
This commit is contained in:
claude@clouddev1
2026-05-20 21:38:08 +00:00
parent ee0dafd86b
commit ed881eea59
8 changed files with 456 additions and 96 deletions
+59 -1
View File
@@ -30,7 +30,7 @@ use crate::dsl::walker::outcome::{
};
pub use context::ColumnInfo;
pub use highlight::highlight_runs;
pub use highlight::{highlight_runs, highlight_runs_in_mode};
pub use outcome::{Diagnostic, Severity};
/// Resolve the hint-panel mode at the end of `source`
@@ -436,6 +436,18 @@ pub fn input_verdict_in_mode(
pub fn input_diagnostics(
source: &str,
schema: Option<&crate::completion::SchemaCache>,
) -> Vec<outcome::Diagnostic> {
input_diagnostics_in_mode(source, schema, crate::mode::Mode::Simple)
}
/// Mode-aware [`input_diagnostics`]. Advanced mode lets the
/// Phase-2 SQL-side diagnostics (ADR-0032 §11) emit alongside
/// the existing DSL diagnostics.
#[must_use]
pub fn input_diagnostics_in_mode(
source: &str,
schema: Option<&crate::completion::SchemaCache>,
mode: crate::mode::Mode,
) -> Vec<outcome::Diagnostic> {
if source.trim().is_empty() {
return Vec::new();
@@ -444,6 +456,7 @@ pub fn input_diagnostics(
context::WalkContext::new,
context::WalkContext::with_schema,
);
ctx.mode = mode;
let (result, _cmd) = walk(source, outcome::WalkBound::EndOfInput, &mut ctx);
result.map_or_else(Vec::new, |r| r.diagnostics)
}
@@ -3832,6 +3845,51 @@ mod tests {
);
}
#[test]
fn sql_case_predicate_warning_fires() {
// ADR-0032 §11.6 — predicate warning fires inside
// `CASE WHEN <bare-col> <op> <literal>` shapes too.
let schema = typed_schema();
let diags = diag_keys(
"select case when price like 5 then 1 else 0 end from products",
&schema,
);
assert!(
diags.iter().any(|d| d.contains("LIKE")),
"expected like_numeric warning inside CASE; got {diags:?}",
);
}
#[test]
fn sql_order_by_predicate_warning_fires() {
// Predicate-shape inside ORDER BY's sql_expr — same
// pass, same warning.
let schema = typed_schema();
let diags = diag_keys(
"select * from products order by price like 5",
&schema,
);
assert!(
diags.iter().any(|d| d.contains("LIKE")),
"expected like_numeric warning inside ORDER BY; got {diags:?}",
);
}
#[test]
fn sql_projection_predicate_warning_fires() {
// Predicate shape used as a projection item (returns
// 0/1). Same warning surface.
let schema = typed_schema();
let diags = diag_keys(
"select price like 5 from products",
&schema,
);
assert!(
diags.iter().any(|d| d.contains("LIKE")),
"expected like_numeric warning inside projection; got {diags:?}",
);
}
#[test]
fn sql_join_on_predicate_warning_fires() {
// Phase-1 gap also affects JOIN ON.