ADR-0024 Phase D: include column name in value-slot hint prose
User-facing improvement: typing into a value slot now surfaces
the column name in the hint. The hint at `insert into Customers
values (` (first column id:int) reads "for `id`: Type an
integer (e.g. 42, -7) or null" instead of the generic
"Type an integer …" prose. After `1, ` the panel updates to
the second column ("for `Name`: Type a quoted string …"). The
same applies to `update T set Email=` and `delete from T where
ts=` — the catalog wrapper threads the column name through.
Implementation:
**`Node::TypedValueSlot.column_name: Option<&'static str>`**
(new field, `src/dsl/grammar/mod.rs`). When `Some`, walker
writes `WalkContext::pending_value_column` on entry; clears
along with `pending_value_type` on inner success.
**Walker driver writes both names** (`src/dsl/walker/driver.rs`):
- `Node::TypedValueSlot` dispatch reads `column_name` and
populates `pending_value_column`.
- `Ident { writes_column: true }` dispatch also writes
`pending_value_column` (using the schema-canonical name when
available, falling back to the user's spelling) so update
set / where positions surface the column name.
**Shared sub-grammars** (`src/dsl/grammar/shared.rs`):
- New `slot_for_column(ty, name)` builds a `TypedValueSlot`
with the embedded leaked column name. Used by
`column_value_list`.
- New `slot_inner_for_type(ty)` returns just the Choice
(without TypedValueSlot wrapper) for slot_for_column to
rebuild.
- `column_value_list` factory now constructs per-column slots
via `slot_for_column(col.user_type, &col.name)`. Each slot
leaks its column name string with the same per-walk Box::leak
pattern the rest of dynamic dispatch uses.
**`WalkContext::pending_value_column: Option<String>`** (new
field, `src/dsl/walker/context.rs`). Pairs with
`pending_value_type` to give the hint resolver both pieces.
**Single-walk hint resolver** (`src/dsl/walker/mod.rs`):
- New `HintResolution { mode: HintMode, column: Option<String> }`
struct.
- New `hint_resolution_at_input(source, schema) -> Option<
HintResolution>` runs one walk and reports both pieces. The
ambient_hint dispatch composes per-column prose from the
result.
- Existing `hint_mode_at_input` / `hint_mode_at_input_with_schema`
preserved as thinner wrappers for tests / future callers
that don't need the column name.
**Catalog wrapper** (`src/friendly/strings/en-US.yaml`,
`src/friendly/keys.rs`):
- New `hint.value_slot_for_column: "for `{column}`: {detail}"`
prefixes the per-type prose with the actual column name when
the walker has it bound. Schemaless fallback continues to use
the generic value-literal prose with no column prefix.
**ambient_hint composes** (`src/input_render.rs`): consults
`hint_resolution_at_input`; when `column` is `Some`, wraps the
type prose through `hint.value_slot_for_column`; otherwise
emits the bare type prose.
Tests (846 total, 0 failing):
- 4 new input_render tests assert column names appear in the
prose at insert/update/where positions plus the
second-insert-value position (proves column tracking advances
with comma).
- All existing tests pass unchanged — the column-name addition
is layered on top of the type-only prose path.
Clippy clean.
This commit is contained in:
@@ -38,6 +38,22 @@ pub struct WalkContext<'a> {
|
||||
/// emit per-type prose ("Type an integer", "Type a date as
|
||||
/// 'YYYY-MM-DD'", …) at empty prefix at typed value slots.
|
||||
pub pending_value_type: Option<crate::dsl::types::Type>,
|
||||
/// The column name (if known) the walker is about to
|
||||
/// consume a value for.
|
||||
///
|
||||
/// Populated by:
|
||||
/// - `Ident { source: Columns, writes_column: true }` for
|
||||
/// `update set <col>=` and `where <col>=` positions, where
|
||||
/// the column ident matches in the path immediately
|
||||
/// before the value slot.
|
||||
/// - `Node::TypedValueSlot { column_name: Some(name), … }`
|
||||
/// for the per-column typed slots in `column_value_list`
|
||||
/// (insert-into-T-values positions, where the column name
|
||||
/// is keyed by position in the table's column list).
|
||||
///
|
||||
/// Cleared on successful inner match alongside
|
||||
/// `pending_value_type`.
|
||||
pub pending_value_column: Option<String>,
|
||||
}
|
||||
|
||||
impl<'a> WalkContext<'a> {
|
||||
@@ -60,6 +76,7 @@ impl<'a> WalkContext<'a> {
|
||||
current_table_columns: None,
|
||||
current_column: None,
|
||||
pending_value_type: None,
|
||||
pending_value_column: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user